Returning a promised wrapped express route to app.

2019-09-06 20:59发布

问题:

I'm looking to make an express route more modular. I was interested in using a promise to read a file then return the route.

Here's the code:

var express = require('express')
var router = express.Router()
var app = express()

var Promise = require("bluebird")
var fs = Promise.promisifyAll(require("fs"))

function promiseRoute(file){
  return fs.readFileAsync(file, "utf8")
  .then(JSON.parse)
  .then(function(file){
    if(!file.url) throw new Error("missing url")
    router.get(file.url, function(req, res, next){
      return res.redirect("/hello")
    })
    return router
  })
}

app.use(promiseRoute("../file.json"))

var server = app.listen(3000, function () {})

also tried

promiseRoute(path.join(__dirname, "./file.json")).then(app.use)

And I'm getting this error.

throw new TypeError('app.use() requires middleware functions')

And this with the promise.

Unhandled rejection TypeError: Cannot read property 'lazyrouter' of undefined
    at use (/project/node_modules/express/lib/application.js:213:7)
    at tryCatcher (/project/node_modules/bluebird/js/main/util.js:24:31)
    at Promise._settlePromiseFromHandler (/project/node_modules/bluebird/js/main/promise.js:489:31)
    at Promise._settlePromiseAt (/project/node_modules/bluebird/js/main/promise.js:565:18)
    at Promise._settlePromises (/project/node_modules/bluebird/js/main/promise.js:681:14)
    at Async._drainQueue (/project/node_modules/bluebird/js/main/async.js:123:16)
    at Async._drainQueues (/project/node_modules/bluebird/js/main/async.js:133:10)
    at Immediate.Async.drainQueues [as _onImmediate] (/project/node_modules/bluebird/js/main/async.js:15:14)
    at processImmediate [as _immediateCallback] (timers.js:371:17)

Also tried this:

promiseRoute(path.join(__dirname, "./file.json")).then(function(router){
  app.use(function(req, res, next){
    return router
  })
})

How can I return promise / route to app.use?

回答1:

app.use requires middleware function. That is, a function that takes (req, res, next).

So overall:

app.use(function(req, res, next){
     promiseRoute(probably_pass_things_in).nodeify(next);
});

The nodeify is to convert a promise to a callback next will take. Note there is third party promise middleware for express you can use.



回答2:

This did the trick:

promiseRoute(path.join(__dirname, "./file.json")).then(function(router){
  app.use(router)
})