'Express middleware - add promise rejection handlers
I have the following simplified middleware function:
router.put('/', function (req, res, next) {
const data = req.body;
const q = req.parsedFilterParam;
const opts = req.parsedQueryOpts;
ResponseCtrl.update(q, data, opts)
.then(stdPromiseResp(res))
.catch(next);
});
I want to add some ability to catch errors to the middleware, just to save some code, something like this:
router.put('/', function (req, res, next) {
const data = req.body;
const q = req.parsedFilterParam;
const opts = req.parsedQueryOpts;
return ResponseCtrl.update(q, data, opts)
.then(stdPromiseResp(res));
});
so we now return the promise in the middleware function, and we can forgo the catch block.
so internally, it might look like this now:
nextMiddlewareFn(req,res,next);
just looking to change it to:
const v = nextMiddlewareFn(req,res,next);
if(v && typeof v.catch === 'function'){
v.catch(next);
});
does anyone know how to do this with Express?
Solution 1:[1]
var router = new ExpressPromiseRouter();
router.get('/foo', function(req, res) {
return somethingPromisey();
});
// or...
router.get('/bar', async function(req, res) {
await somethingPromisey();
});
app.use(router);
PS: There's no need to be afraid of async
/await
on performance grounds. There is no appreciable difference vs regular functions with promises.
Solution 2:[2]
You may also want to try the general purpose solution: asyncback.
For usage in ExpressJS middle-ware:
const asyncback = require('asyncback');
app.get('/users', asyncback(async (req, res) => {
const users = await User.find({ 'banned': false });
const offer = await Offers.findOne({ 'active': true });
res.json({ 'users': users, 'offer': offer });
}));
When the async function returns or throws, the next
callback passed by express to asyncback is automatically called accordingly.
Solution 3:[3]
Note to the reader, the following actually doesn't work:
router.put('/', async function (req, res, next) {
const data = req.body;
const q = req.parsedFilterParam;
const opts = req.parsedQueryOpts;
await ResponseCtrl.update(q, data, opts)
.then(stdPromiseResp(res));
});
if the promise is rejected, the try/catch that surrounds each piece of middleware won't actually pick it up, if the promise is rejected, it will bubble up to an unhandledRejection handler if there is one.
I would look forward to a good solution though which:
- could be typed with TypeScript
- doesn't use async/await.
This is the solution that worked best for me as of now:
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | josh3736 |
Solution 2 | |
Solution 3 |