Using Node.js + Express (4) + Mongoose (using promises rather than callbacks), I can’t sort out how to tidy up my error handling.
What I've got (rather simplified) is:
app.get('/xxx/:id', function(request, response) {
Xxx.findById(request.params.id).exec()
.then(function(xxx) {
if (xxx == null) throw Error('Xxx '+request.params.id+' not found');
response.send('Found xxx '+request.params.id);
})
.then(null, function(error) { // promise rejected
switch (error.name) {
case 'Error':
response.status(404).send(error.message); // xxx not found
break;
case 'CastError':
response.status(404).send('Invalid id '+request.params.id);
break;
default:
response.status(500).send(error.message);
break;
}
});
});
Here, in the switch in the ‘promise rejected’ section, the Error
is the error I threw myself for a potentially valid id which is not found, the CastError
is Cast to ObjectId failed thrown by Mongoose for an invalid id, and the 500 error can for instance be triggered by mistyping throw Error()
as throw Err()
(causing a ReferenceError: Err is not defined).
But like this, every one of my routes has this great big clumsy switch to handle the different errors.
How can I centralise the error handling? Can the switch be tucked away into some middleware somehow?
(I did hope I could just re-throw using throw error;
within the 'promise rejected' block, but I haven’t been able to make it work).
I would create middleware to handle errors. Using next()
for 404s. and next(err)
for other errors.
app.get('/xxx/:id', function(req, res, next) {
Xxx.findById(req.params.id).exec()
.then(function(xxx) {
if (xxx == null) return next(); // Not found
return res.send('Found xxx '+request.params.id);
})
.then(null, function(err) {
return next(err);
});
});
404 handler
app.use(function(req, res) {
return res.send('404');
});
Error handler
app.use(function(err, req, res) {
switch (err.name) {
case 'CastError':
res.status(400); // Bad Request
return res.send('400');
default:
res.status(500); // Internal server error
return res.send('500');
}
});
You can improve upon this more by sending a json response like:
return res.json({
status: 'OK',
result: someResult
});
or
return res.json({
status: 'error',
message: err
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With