5 ms·
Node.js error handling
- chrisringrose 14y agoFinally a good explanation of error handling in node.js. Cheers!
- benatkin 14y agoThere seems to be an error in the final code snippet. Instead of d.intercept it should be mainDomain.intercept. Here's the original example: http://nodejs.org/api/domain.html#domain_example_1 http://nodejs.org/api/domain.html#domain_example_1
- beastmcbeast 14y agoApologies for that, I've updated the example. Thanks for pointing it out.
- STRML 14y agoUnfortunately error handling in Node.js is a total mess. As with most new technologies there are few standards and whatever standards there are are subject to change. It was only a short time ago that many Node.js libs were being produced with promises. The most common style I see today is this callback style: doAsyncCall(function(err, result){ if(err){ // handle err } }); Unfortunately this is prone to error. When writing any sort of asynchronous function - that is, 'doAsyncCall' itself, you need to write it in the following way: function doAsyncCall(cb){ // .. do some async stuff if(// error has been thrown){ callback(err); } else { callback(null /* this is where confusion happens */, result); } } When writing such code you need to be very consistent and very aware of what error handling style is being used. It can be jarring for some to intentionally pass null as the first argument. I am personally a fan of the `if(result typeof Error)` style but it is not common. Many frequently used libraries, like Mongoose, use the (err, result) style. Because any async call can theoretically fail, and because you need to catch every potential error, it is common for starting programmers (and even experienced ones) to miss an edge case or two. I advocate using upstart or a similar scheme to make sure your Node server stays alive, even if you happen to have missed an error somewhere.
- coryvirok 14y agoOne of the things I love about node.js is that it forces you to come up with a style and stick with it for things like this. At http://ratchet.io http://ratchet.io our API servers are written in node.js and we chose the foo(err, callback) method. I personally love this style even though it makes you write more boiler-plate code, it forces you to write exception-safe code from the start. Also, it forces a structure on all of your code that you can instantly recognize as missing if someone forgets to check for err in the callback. If you can stick with the style, it's fairly difficult to write code that doesn't deal with errors gracefully.
- STRML 14y agoI agree. One of the advantages of the (err, result) style is that it puts error handling directly in your face. The `result typeof Error` style does not. In any case all I care about is that we choose one, and (err, result) is gaining traction, which is fine. While many are excited about domains, I am not. From my perspective, in practice, it will just add another incompatible style onto the pile.
- mcantelon 14y agoYeah, domains seem like a desperate solution. Will be interesting to see what eventually becomes the standard.
- kevingadd 14y agoHow do you deal with code where the author forgot to handle all of the failure cases and invoke the callback?
- STRML 14y agoTo be honest... since you can't try/catch, you can't do much. You can catch the exception with something like this: process.on('uncaughtException', function (err) { console.err("Uncaught exception: " + err); console.err("Uncaught exception stack: " + err.stack); }); I use the built-in clustering module (implementation is very simple) so a simple worker crash will result in the error being logged & the worker being restarted. That's about the best you can do, unfortunately. You could always monkey patch the lib if you can figure out where it's crashing. I recommend Longjohn(https://github.com/mattinsler/longjohn https://github.com/mattinsler/longjohn) for these sorts of situations; the extra stack trace lines become invaluable.
- PhrosTT 14y agoI actually just wrote a Node + Express + Backbone error handling system today. I've been staying sane through the use of the 'Q' promise package (https://github.com/kriskowal/q https://github.com/kriskowal/q). For example, in the below code chunk any errors thrown in makeEmailConfirmation or sendEmailConfirmation will land in the .fail() catch block. I believe using a promise system is the only way to avoid callback hell. var deferred = Q.defer(); ... Storage.CustomLinks.makeEmailConfirmationLink(user) .then(function(link) { return Email.sendEmailConfirmation(user, link); }) .then(function(result) { deferred.resolve(result); }) .fail(function(err) { deferred.reject(new ServerError(err)); }) .end(); ... return deferred.promise;
- beefsack 14y agoI've recently written an application extensively using Q, and was very pleased at how clean my code ended up being. Particularly in comparison to how node.js code tends to end up looking once your callback pyramids start to grow.
- olegp 14y agoYou can also use fibers and make the code appear synchronous, which gives you the ability to use exceptions for error handling.
- rogerhcastillo 14y ago+1 for promises based exception handling. I have used Q for a number of applications. Q really simplifies error handling and by chaining error propagation forward to asynchronous result consumers.
- aneth4 14y agoSeems like promises (e.g. Q) use a other sort of error handling similar to domains, but win a cleaner syntax the addition of the promises functionality.
- aneth4 14y agoWow, I should proof read on my iphone.
- scriby 14y agoWill these examples protect you from thrown exceptions? Null reference exception? Oops, your callback isn't getting called -- and you're probably leaking resources or leaving things in an inconsistent state. So the recommendation is to restart the process - but let's not forget that hundreds+ of other requests could currently be in the pipeline - are we just going to abort those too? Ok, we'll clearly the solution is to wrap all our callbacks with try/catch! Shoot me now... For large, sprawling applications used to support a business, something like https://github.com/scriby/asyncblock https://github.com/scriby/asyncblock can resolve most of the headaches with async code, including error handling. It's worked out well for my team at work, which is building a "very large" node application. Disclaimer: Asyncblock is my pet project.