Error Handling in Nodejs
joyent.com
joyent.com
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.
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;
});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!
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.
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.
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.
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.
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.
something().then(function(){
setTimeout(function(){
whoops_not_a_function();
}, 1000);
}).catch(function(){
// nope, nothing to catch
}); 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).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.