I've been using the 'async' lib in Node.js (I switched from 'step' lib) and I find the Promises' .then() method chaining and exception throwing really similar to async:
async.waterfall({
'step1':function(next) { next(null,1); },
'step2':function(num,next) { next(null,num,2); },
'step3':function(num1,num2,next) {next(null,num1+num2);}
},
function result(err,num) {
if (err)
console.error(err);
else
console.log("the number is:",num); //output: the number is: 3
});
If any exceptions get thrown, the chain is interrupted and the last function gets called with some err. That's just the 'waterfall' style. There are lots of other methods that make the callback hell very manageable. In fact, I don't know why I would use Promises over what async provides. Can anyone provide a reason to, aside from _some_ syntax sugar?
I have not dived into async, so it may have the ability to handle the following and I just don't know it. But here are the things I think it's missing:
- Interception of not only errors explicitly passed up to the callback, but also thrown exceptions (see the paragraph containing "we take care of both intentional and unintentional exceptions")
- Per-task error interception, translation, and re-throwing
- Guarantees like "never both fulfilled and rejected" or "the state never transitions once it's fulfilled or rejected" or "only at most one handler is called, at most one time". For example real bugs in popular libraries have stemmed from calling callbacks with both an error and a result, or calling them twice (with different parameters each time). A speaker at HuJS gave an example of this in one of TJ Hollowaychuk's libraries.
First and third are definitely true for async. I'm not sure about the second, but it looks like something one would achieve with a try/catch block inside a task.