I am working with a partner on a project. He has written a lot of code in Node.js+Express, but we've been running into issues with the architecture.
To remedy this, my primary role has been to figure out the best way to architect a Node.js+Express application. I've run into two scenarios, dealing with errors, and I'd like some suggestions.
First, how do I capture top-level exceptions? The last thing I want is for a bug to completely kill the node process. I want to continue serving users in the face of any error.
Secondly, some errors are passed back via callbacks (we're using caolan / async). As part of each route handler, either we render a view (GET), redirect to another route (POST) and we want to redirect to an error screen with a custom error message. How can I make sure to capture this logic in one place?
First, how do I capture top-level exceptions? The last thing I want is for a bug to completely kill the node process. I want to continue serving users in the face of any error.
Edit: I think node's philosophy in general is that any uncaught exceptions should kill the process, and that you should run your node app under some kind of process monitor with appropriate logging facilities. The following advice is regarding any other errors you might encounter in your express route handlers etc.
Express has a general errorHandler, which should capture all thrown errors as well as everything passed as a parameter to next
in your routes/middlewares, and respond with 500 Internal Server Error
.
Secondly, some errors are passed back via callbacks (we're using caolan / async). As part of each route handler, either we render a view (GET), redirect to another route (POST) and we want to redirect to an error screen with a custom error message. How can I make sure to capture this logic in one place?
You could create a custom handleError
, which you call in each callback like so:
async.series(..., function(err, results) {
if(err)
return handleError(req, res, err);
// ...
});
Or you could just pass the errors on with next(err)
and implement your custom error handler as described here: http://expressjs.com/guide/error-handling.html
Top level exceptions:
You can use the uncaughtException event from process, but it's generally not recommended.
Often applications will go into a corrupted state (eg. you have some state which typically gets set, but the exception caused that not to happen) when an exception is thrown. Then, it will just cause more and more errors from there on onwards.
A recommended approach is to use something like forever to automatically restart the app in case it crashes. This way you will have the application in a sane state even after a crash.
Error handling in express:
You can create a new Error instance and pass it to the next callback in the chain.
Eg.
express.get('/some/url', function(req, res, next) {
//something here
if(error) {
next(new Error('blah blah'));
}
});
To handle the error from here on onwards, you can set an error handler. See express docs on error handling
Checkout the excellent log-handling module Winston: https://github.com/flatiron/winston
It allows you to configure exception handling in a manner that will not only log it, but will allow the process to continue. And, since these would obviously be serious issues, you can even configure Winston to send out emails on specific event types (like exceptions).