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.
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.
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.
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 :)
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.
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.
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.
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.
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.