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.

Reply via email to