promises

now that promises are going mainstream, i’m trying to think of how to make express more async friendly. an idea is to use promises.

  • next() now returns a promise
  • if middleware returns a promise, that promise is resolved and propagated up next()s
app.use(function (req, res, next) {
  // a promise must be returned, 
  // otherwise the function will be assumed to be synchronous
  return User.get(req.session.userid).then(function (user) {
    req.user = user
  })
  .then(next) // execute all downstream middleware
  .then(function () {
    // send a response after all downstream middleware have executed
    // this is equivalent to koa's "upstream"
    res.send(user)
  })
})

Error handlers are now more koa-like:

app.use(function (req, res, next) {
  return next().catch(function (err) {
    // a custom error handler
    if (res.headerSent) return
    res.statusCode = err.status || 500
    res.send(err.message) 
  })
})

app.use(function (req, res) {
  throw new Error('hahahah')
})

Pros:

  • it should be backwards compatible since you don’t have to resolve the promise returned from next()
  • much easier error handling including throwing
  • solves issues shown in #2255
  • no more fn.length checking _
  • could probably easily upgrade to es7 async functions

Cons:

  • promises
  • upgrading middleware and supporting both signatures might be a pain in the ass
  • probably a lot slower

Author: Fantashit

4 thoughts on “promises

  1. Any updates on this? Would be nice if middleware could return a promise as an alternative to calling next()/next(err).

    Edit: Oops, just noticed it is coming in v5: #2237

  2. I’m going to close this issue now that Express.js 5.0.0-alpha.7 has been published which includes the initial support for Promises in the router. Middleware and handlers can now return promises and if the promise is rejected, next(err) will be called with err being the value of the rejection. The implementation is seeking feedback from real usage, and please open any feedback as a new issue, either in this issue tracker or in the router issue tracker.

    I am currently working on writing up Express.js-specific documentation on this feature, but in the meantime, the documentation can be found in the router repository:

    https://github.com/pillarjs/router/tree/v2.0.0-alpha.1#middleware

    The function can optionally return a Promise object. If a Promise object is returned from the function, the router will attach an onRejected callback using .then. If the promise is rejected, next will be called with the rejected value, or an error if the value is falsy.

Comments are closed.