I believe that labeling a statement you disagree with "a flat out lie" is a pointlessly harsh response. But arguably calling that "screaming" is just as inadequate. I apologize ;)
Now to the point. If you're facing this problem using promises, I would argue that you're using promises the wrong way - by making wrong assumptions. When dealing with futures, making any assumption about the callback being invoked synchronously or asynchronously is wrong (if for no other reason, then because it is non-essential to the nature of promises). It's not unlike making two async calls and expecting the callbacks in the same order. Wrong assumption (although a not entirely surprising one). That doesn't mean that asynchronous programming is broken. Only that it requires a little effort to understand it. Now it we put aside the fact for a moment, that promises are a functional concept, and look at them from an imperative perspective, it is important to notice that, with promises, initiating the asynchronous operation and defining a handler are two different steps. With plain callbacks, this is one single step. And the callback is invoked, regardless whether we're ready for it, or not. This is particularly problematic, when the callback is synchronous, but the problem is broader than that. With promises, we do not have this problem at all. We cannot be caught with our pants down, because we register the handler when we're ready. Here's Oleg's code with promises: var todo = 0; function done() { todo--; if (!todo) callback(); } todo++; var a = do_a(); todo++; var b = something ? do_b() : do_nothing(); a.when(done); b.when(done); We make no assumptions about when our callbacks are called. The result of `do_nothing()` will probably invoke callbacks immediately. It does not concern us. Because we have the luxury of choosing an arbitrary point in time to register our handlers, we can in turn guarantee the one critical assumption: that we are ready to handle the result at that point. We have all our state setup, as we see fit. In consequence, we just as well have the liberty of replacing the last two lines like so: do_c().when(function () { a.when(done); b.when(done); }); Or what not. Probably `do_c` will take much longer then just one tick. Or not. Who knows? Who cares? Also `a` might finish before we get to register a handler. Again, we do not care. Ultimately, it means, we can also condense the code and spare ourselves fiddling with counters: var a = do_a(), b = something ? do_b() : do_nothing(); do_c().when(function () { a.when(function () { b.when(function () { callback(); }); }); }); Lastly, let's also keep in mind, that this is NOT AT ALL an idiomatic use of promises. I would say that calling this the "use of promises" is because you're using promises instead of callbacks is a bit saying you're doing functional programming because you use `forEach` instead of plain loops. The point of promises is to have first class values that can then be composed. That would be something like: Promise.all(do_a(), something ? do_b() : do_nothing(), do_c()).when(callback); No local variables, no state, no trip-wires. If you're really using promises "the right way", then the presence of captured mutable local variables (in the sense that you actually write to them) is a pretty serious smell. At the bottom line, the problem at hand is easily side-stepped, even in the most imperative variant, as seen at the beginning. It boils down to just one ruel: You must make no assumptions that overstep the boundaries of the solution space your abstractions span, for Zalgo's realm lies beyond them. With direct callbacks, you specify the first operation, and right beside it the code that should handle its result. And only because you are forced into this highly illogical structure, do you then demand the invocation to be guaranteed asynchronous, because you have been forced to define at the beginning of a sequence, what you want executed at its end - yes, we're all used to it, but quite frankly it's pretty twisted. With promises you can explicitly say "execute this no sooner than this point in the execution flow". Which I think is far more powerful, especially since (without further noise) you can decide to handle parallel results in the order that makes sense to you and not in the order they arrive. So you write code in an order that makes sense to mortals and you make no superfluous assumptions. Et voilĂ , it will not actually even matter whether or not your promises are forced async or not. What you will get for free is the ability to execute the same code in an environment that does not have an event loop but still mimics the same APIs by returning synchronous promises. Not necessarily useful, but just an illustration of how powerful it is to assume only the necessary. Anyway, I see I've written far to much already. But I hope it clarifies what I mean. Regards, Juraj -- -- Job Board: http://jobs.nodejs.org/ Posting guidelines: https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines You received this message because you are subscribed to the Google Groups "nodejs" group. To post to this group, send email to nodejs@googlegroups.com To unsubscribe from this group, send email to nodejs+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/nodejs?hl=en?hl=en --- You received this message because you are subscribed to the Google Groups "nodejs" group. To unsubscribe from this group and stop receiving emails from it, send an email to nodejs+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.