Skip to content

Instantly share code, notes, and snippets.

@trenskow
Last active December 14, 2018 00:41
Show Gist options
  • Save trenskow/62405c4cefd4b5b2e00e82768c978e38 to your computer and use it in GitHub Desktop.
Save trenskow/62405c4cefd4b5b2e00e82768c978e38 to your computer and use it in GitHub Desktop.
A hack that makes express accept async methods.
const express = require('express');
const app = express();
app.get(
'/',
async (req, res) => {
res.json(await something());
});
app.get(
'/:user/',
async (req) => {
req.user = await User.get(req.params.user);
if (!req.user) throw new Error('User not found'); // Becomes next(err).
},
// Async and non-async can be mixed.
(req, res) => {
res.json(req.user);
}
);
const express = require('express'),
methods = require('methods'),
flatten = require('array-flatten');
// We iterate through the router keys.
methods.concat(['use','param','route']).forEach((key) => {
// Keep the old implementation.
let old = express.Router[key];
// Replace with new.
express.Router[key] = function(...args) {
// Flatten arguments (express does this also).
args = flatten(args);
// Map the arguments.
args = args.map((arg) => {
// If argument is not an async function - we just return it.
if (arg.constructor.name !== 'AsyncFunction') return arg;
// - otherwise we wrap it in a traditional route and return that.
return (req, res, next, ...args) => {
// Remark next is not forwarded.
arg.apply(null, [req, res].concat(args))
.then(() => {
if (!res.headersSent) next();
})
.catch((err) => {
next(err);
});
};
});
// Apply new arguments to old implementation.
return old.apply(this, args);
};
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment