Passing anything to next(expect the string 'route') will pass to 4 arg error middleware
Async Solutions
Async Wrapper
app.get('*', wrapAsync(async (req, res) => {
await new Promise(resolve => setTimeout(() => resolve(), 50));
// Async error!
throw new Error('woops');
}));
app.use(function(error, req, res, next) {
// Gets called because of `wrapAsync()`
res.json({ message: error.message });
});
function wrapAsync(fn) {
return function(req, res, next) {
// Make sure to .catch() any errors and pass them along to the `next()` middleware in the chain, in this case the error handler.
fn(req, res, next).catch(next);
};
}
app.get('/', function (req, res, next) {
Promise.resolve().then(function () {
throw new Error('BROKEN')
}).catch(next) // Errors will be passed to Express.
})
Error Handler
If any route throws an error, it will go to first error handler which has specifically 4 args:
If streaming resp and you get an error, default error handler properly closes the connection and fails the request. So you should delegate to it, if headers have already been sent to the client:
function errorHandler (err, req, res, next) {
if (res.headersSent) {
return next(err)
}
res.status(500)
res.render('error', { error: err })
}