These two middleware functions behave differently and I cannot figure out why:
Here, the error will get trapped by try/catch:
router.get('/force_async_error/0', async function (req, res, next) {
try{
await Promise.reject(new Error('my zoom 0'));
}
catch(err){
next(err);
}
});
But here, the error will not get trapped by try/catch:
router.get('/force_async_error/1', async function (req, res, next) {
await Promise.reject(new Error('my zoom 1'));
});
I thought Express wrapped all middleware functions with try/catch, so I don't see how it would behave differently?
I looked into the Express source, and the handler looks like:
Layer.prototype.handle_request = function handle(req, res, next) {
var fn = this.handle;
if (fn.length > 3) {
// not a standard request handler
return next();
}
try {
fn(req, res, next); // shouldn't this trap the async/await error?
} catch (err) {
next(err);
}
};
so why doesn't the try/catch there capture the thrown error?
This is because the call is asynchronous, take this code :
If you run it you should see that the error is triggered after
Point of non-return. When we're at thethrowline it's too late, we're outside oftry/catch. At this moment if an error is thrown it'll be uncaught.You can work around this by using
async/awaitin the caller (doesn't matter for the callee), ie :Finally, this means that for Express to handle async errors you would need to change the code to :
A better workaround:
Define a
wrapfunction like this :And use it like this :