Hacker News new | past | comments | ask | show | jobs | submit login
Error Handling in Nodejs (joyent.com)
86 points by jessaustin on July 17, 2015 | hide | past | favorite | 29 comments



This gets so much easier with promises it's amazing:

1. You can `throw` in async functions (when things are promisified) and `.catch` async errors.

2. You can't forget the error handling or ignore the `err` parameter, it will propagate until you handle it.

3. Did I mention propagation like with sync errors yet?

4. It's easy to build exception hierarchies. Libraries like bluebird provide typed and predicate catch blocks that let you do exception handling the way you want like in other languages.

5. Did I mention async/await or coroutines yet? You can use normal try/catch with promises as a language feature.

6. No Zalgo, if something might be async it should always be async to preserve execution order. `then` always runs asynchronously which means no timing issues and race conditions in errors and success values.


The biggest mistake in JS Harmony is silently swallowing async errors by default unless you add a .catch to a Promise chain.


Agreed! I literally just dealt with this eariler in the work week, spent hours trying to figure out why an error wasn't properly being thrown in my unit tests ... forgot to catch the promise chain -.-

This applies to functions that are async as well in babel:

    async function get(url) {
        throw new Error('hi there');
    }

    // wont throw the error
    get('http://google.com');

    // catch the error
    get('http://google.com').catch(function(err) {
        throw err;
    });


Not if I can help it :) In io.js this is no longer an issue, you have a process event you can catch on "silent errors" to make them loud. This lands in NodeJS soon. Bluebird promises don't behave this way and have never done so.


Maybe there's a nuance between "possibly unhandled" and "unhandled" ?

I was bitten by bluebird quietly eating exceptions on at least one codebase. I fixed it by re-throwing them via: https://github.com/petkaantonov/bluebird/blob/master/API.md#...

edit: bluebird also exposes a process-level event, now, too!


great! BTW would you use bluebird or es6 promises if starting a new project today?


inglor is a contributor to Bluebird, so I'd guess he'd say Bluebird. Bluebird is the much faster option and has a lot more features, if you're using babel (and a recent node/io.js) you can transpile async/await to bluebird coroutines for maximum performance and syntactic beauty.


Is there any chance Bluebird will become the standard in the future? Not sure if it makes sense to use a nonstandard approach, but would love to be convinced otherwise.


IMHO, very doubtful; Bluebird has a lot of (very useful) features that would be pretty burdensome to put into a specification.

On the other hand, there's really no reason not to use Bluebird. It's easy to ensure that a promise you receive is a Bluebird promise:

    import Bluebird from 'bluebird';
    const bluebirdPromise = Bluebird.resolve(promise);
If `promise` is a Bluebird promise that will be a no-op, and if it's a foreign promise or thennable you'll get a new Bluebird promise that will resolve/reject when the foreign one does. (This is standard behavior; see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...)

Since Bluebird promises are thennables, the reverse will be true if they're consumed by a different promise library.

Given Bluebird's speed, superior debuggability, and features, there's really no reason not to use it a this point.


thanks much for the explanation. I will try bluebird.


Chrome at least logs the error to console

http://jsfiddle.net/sb1zqjdm/ (using native promises)

And it seems that the "Pause on exceptions" debugger feature works on unhandled promise errors. Doesn't seem too bad to me.


This is a recent addition due to complaints like mine. Hopefully it becomes standard, because it's the way it should have always been.


Well - the moral is to complain more, when I wrote and advocated for detection in io.js I needed people on my side - Domenic needs people to complain and help now for the browser spec - we're always a hand short :)


Wonder whether there is anything to add to the standard. Isn't this just a devtools issue?


The standard should simply be changed to throw by default, but I guess the train has already left the station and so we're left with "bugs by design" before the spec has even been fully implemented by all vendors :(

But then again, in it's current "minimal" state of design, the Harmony Promises are inferior to any of the dedicated Promise A Plus implementations out there (e.g. Bluebird) and at least under Node there is little to no reason to use the built-in Promise object at this point in time.



This has been my biggest pain point with Promises, I have spent hours trying to debug an issue only to find out I hadn't used an error handler in a Promise somewhere and an error was being thrown. It is so frustrating.

I know some Promise libraries have an option to report unhandled errors which makes life a lot easier but there really should be something natively too.


process.on('unhandledRejection', function(promise,reason) {` since io.js 1.3


I haven't looked at io.js in a short while. Does it log to console.error by default (like Chrome now does)?

This mistake is going to be most frustrating for those who don't realize that "unhandledRejection" is a case they even need to consider. People learning JS and having nothing happen when they run (erroneous) code are going to be pulling their hair out.


This is currently being discussed in io.js (and remember it's being backported to the main NodeJS branch). Feel free to come participate in the discussion.


FWIW, I think JS swallows all async errors regardless of whether you use .catch(). If the error is thrown async, you can't catch it. Right?


No. This is the whole point of promises.


Perhaps the gp meant this case?

   something().then(function(){  
      setTimeout(function(){  
        whoops_not_a_function();  
      }, 1000);  
   }).catch(function(){  
      // nope, nothing to catch  
   });


No built-in help with native promises, but with something like Bluebird you'd prefer:

   something().then(() => {  
      return Promise.delay(1000).then(() => {  
        whoops_not_a_function();  
      });  
   }).catch(() => {  
      // whoops_not_a_function is not defined  
   });
...or write Promise_delay yourself on top of native promises (but really just use Bluebird).


Yup this is what I meant. Thanks. Yeah arrow functions help.


I've been using Babel to experience the ES6/7 world and it's a great experience to use async/await among else.

Like others have said the error handling is not ok, however I want to focus on another related thing.

The use of try{}catch{} for handling errors. Awaken by a section on Pragmatic Programmer and a post [1] of ZeroMQ's Martin Sústrik on (C) error handling. It seems logical to me that try/catch should be used for unexpected behavior and not for expected "falsy" results which is a core case for their current use on ES6/7.

It is convenient to use try/catch compared to past alternatives, but it doesn't feel nor is designed right. Instead of just going with it, until we get terribly tired of it and do something, it's still early enough to have a proper solution in place.

Not sure if any committee is working on this or something else is planned.

[1]: http://250bpm.com/blog:4


Very good article. It is also good to see Joyent writing Node documentation, I hope they can centralize the Node ecosystem and avoid fragmentation while take benefit of an open develop with IO.js fork.


That document has been around since March of last year; it's not a terribly recent thing. See also: https://www.joyent.com/blog/best-practices-for-error-handlin...


Presumably TFA isn't dated because it's considered "timeless". Nevertheless if I could still edit the title I'd add a "(2014)".




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: