Le 09/11/2012 17:33, Mark S. Miller a écrit :
Hi David, thanks for your thoughtful post. I've always used the two-arg form of .then[1], but your post makes a strong case for more often using separate one-arg .then and .fail calls. I say only "more often" because the two arg form can easily make distinctions that the one-arg forms cannot

    var p2 = Q(p1).then(val => { throw foo(val); },
reason => { return bar(reason); });

is different than either of the one-arg chainings. It'll be interesting to look over old code and see how often this difference matters. My guess is it usually doesn't, in which case your style should dominate.
Interesting example. Let's compare it with:

    var p2 = p1.then(val => { throw foo(val); })
                       .fail(reason => { return bar(reason); });

With this given order, the .fail catches the error in the .then callback.
There is an information loss in the fact that in the fail callback, it may not be clear whether the error came from p1 or the .then callback. In my experience, it was never a worthwhile distinction (I just cared about "an error happened somewhere"), so I guess the 80% case is covered.

In case it really matters, the value thrown in the .then could be made distinguishable from expected thrown errors of p1 so that the callback can compare and choose a different behavior for each case.
Also, it's still possible to hook the .fail to p1 directly if necessary.

I feel the one-arg version works fine. As you pointed out, there is a minor information loss, but it's not that hard to work around in the cases where it matters (I've seen you seem to agree, but I felt it was important to do the analysis of the differences in both cases).


[1] In my code and in my Q specs <http://wiki.ecmascript.org/doku.php?id=strawman:concurrency> and implementations <http://code.google.com/p/google-caja/source/browse/trunk/src/com/google/caja/ses/makeQ.js>, I have been using "when" rather than "then". Because these are otherwise compatible AFAICT with A+, for the sake of consensus I'm willing to change this to "then" everywhere. But before I do, I'd like to make one last plea for "when" and see how this community responds.

The word "when" is clearly temporal, and suggests postponing something until some enabling condition. This seems perfect. The word "then" in programming is most closely associated with the concept of an "if then else", even though curly bracket languages never spell out the "then". When I look at your .then/.fail examples, the first thought that always pops into my head is "Shouldn't the opposite of .then be .else ?" Of course .fail is appropriate and .else is not. But isn't .then inappropriate for the same reason?
I have to admit that I haven't paid close attention. For me, .then felt relevant as a form of punctuation like semi-colons for the synchronous style:

    p.then(doThis)
      .then(doThat)
      .then(...)

    // akin to
    var p2 = doThis(p);
    var p3 = doThat(p2);
    ...

JavaScript is a bit special with semicolon, but in some other major languages, a semi-colon is a language construct to separate 2 steps in an algorithm and mean "do this then that". I used .then because of my experience with Q, but if "when" is more accurate, I'll be fine with when.


On Fri, Nov 9, 2012 at 4:33 AM, David Bruant <[email protected] <mailto:[email protected]>> wrote:

    [...]
    ## Q.all
    My favorite feature is the Q.all function. Q.all accepts an array
    of promises and returns a promise which will be fulfilled when all
    promises are. The resolution values are the different promises
    resolution values:

        var someData1P = query(q1);
        var someData2P = query(q2);
        var someData3P = fetch(url); // HTTP GET returning a promise

        Q.all([someData1P, someData2P, someData3P])
            .then(function(someData1, someData2, someData3){
                // do something when all data are back
            })

    I used this extensively and it's been extremely helpful.
    Personally, to synchronize different async operations, I've never
    read code more elegant than what Q.all offers. I'm interested in
    hearing what other's experience is on that point.
    Arguably, Q.all could take several arguments instead of accepting
    only an array (that's one thing I'd change). Maybe there is a good
    reason to enforce an array, but I don't know it.


I originally speced it to take varargs, but I was thinking in ES6 terms where "..." is already supported. Kris Kowal points out that most usage of Q today, for obvious reasons, is pre-ES6. The var-args form means that a Q.all on a computed list would require usage of .apply, which is much uglier than the extra square brackets for the non-computed case.
That makes a lot of sense.
Assuming arrays and promises are unambiguously distinguishable, the Q.all feature could be polymorphic and take either one array as argument or a bunch or promises and have the expected behavior in each case.


    # Promises and progress

    Since I started talking about promises, I've had discussions with
    people and one thing that came about a couple of times was the
    idea of "progress" or how promises relate to streams.

    The way I see promises, they have 3 states:
    unfulfilled/resolved/broken.


Sigh. The fact that even you get confused on the terminology makes me think that no state should ever be named "un" anything. Let's stick with the A+ terminology: pending/fulfilled/rejected.
Sounds good to me. I'll pull my "non-native English speaker" card here, because I don't understand the difference between your terminology and the one I chose.

David
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to