express-promisify
v0.1.0express-promisify
Return Promises from Express middleware and route callbacks
Allow your Express middleware and route callbacks to return a Promise. When a Promise is fulfilled, the result is placed on the res
object for use in subsequent middleware. When a Promise is rejected or an error is thrown within one, the next
function is called to invoke your error handling middleware.
Getting Started
var express = require('express');
var app = express(app);
var expressPromisify = require('express-promisify');
expressPromisify(app);
As seen above, pass your Express app to expressPromisify
. This will modify the app.use
and app.VERB
methods for the given app. For more information, see the "How It Works" section below.
Middleware and route callbacks can be defined and added as usual, but now you can optionally return a Promise. (Note that if you do not return a Promise or respond to the request you will still need to call next
to contine to the next middleware or route callback.)
In the following example, db.query
returns a Promise that is fulfilled when the query's results have been retrieved. The end result is stored on res.result
when a Promise is fulfilled.
function getUserFromDatabase(req, res) {
return db.query('SELECT * FROM users WHERE id = ?', req.params.id);
};
function respond(req, res) {
if (res.result) {
res.json(res.result);
} else {
res.send(404);
}
};
app.get('/users/:id', getUserFromDatabase, respond);
The respond
function in this example is sends a response with the result of the Promise as JSON or a 404 if the query ended up having no result. In a real-world application, this function might also handle responding with a different content type based on the request's Accept
header. This is a good way to share common code with several routes in your application.
Options
Result Property on res
The property on res
in which the Promise result is stored can be changed. This may be useful if for some reason you already have a res.result
property. For example, to use a property called "promiseResult" instead:
expressPromisify.resultProperty = 'promiseResult';
Custom Fulfillment and Rejection Handlers
You can supply your own fulfillment and rejection handlers by overriding the expressPromisify.fulfillmentHandler
and/or expressPromisify.rejectionHandler
methods.
These methods get passed req
, res
, and next
when a Promise returned by middleware or a route callback is fullfilled or rejected, and return a function that is the fulfillment or rejection handler, respectively.
The example below shows a fulfillment handler that will automatically respond with the result of a Promise if it is a string, rather than placing the result on the res
object.
expressPromisify.fulfillmentHandler = function(req, res, next) {
return function(result) { // this is what will be passed to `then`
if (typeof result === 'string') {
res.send(result);
} else {
res[expressPromisify.resultProperty] = result;
next();
}
};
};
Note the default fulfillment and rejection handlers will be replaced with your custom ones. As shown in the example, to continue placing results on res
for non-string values, that logic must be included as part of the custom handler. Also remember to call next
for cases where you will need to continue to subsequent middleware or route callbacks.
How It Works
The app.use
and app.VERB
methods on the Express app that is passed into the expressPromisify
are proxied to "promisify" any middleware or route callbacks that are passed into them. When you add middleware or route callbacks with these replacement methods, the functions you pass into them will be proxied to:
- Execute the original function
- Check if it returns a Promise, and if so...
- Call the fulfillment or rejection function, depending on if the Promise was fulfilled or rejected
When using the default fulfillment and rejection handlers, the next
function will automatically be called to continue to the next middleware or route callback, if any. If the Promise returned by the function is rejected, next
is called with the rejection reason, typically an error, as its argument; your error handling middleware will receive this reason so it can be handled accordingly.
Metadata
- MIT
- Whatever
- Jason Sandmeyer
- released 7/3/2014