jquery/jquery — pull request #1315 by terrycojones (2013-07-27 02:48:58+00:00)
Title: A different jQuery.when command (when2)

I'm not sure if this belongs in a pull request. I'm sending it out for discussion. Maybe it should just be a totally separate module.

The patch adds a `jQuery.when2` function. The main differences from `jQuery.when` are:

* when2 must be called with a list as its first argument.
* An options object may be passed as a second argument.
* If `options.resolveOnFirstSuccess` is `true`, the deferred returned by when2 will be resolved as soon as any of the passed deferreds resolves. In this case the resolve value will be a list [index, value], where index is the index of the deferred that fired. If non-deferreds are in the arguments to when2, the first one seen will trigger the resolve (not very useful, but consistent).
* If `options.failOnFirstError` is `false`, the deferred returned by when2 will never fail. It will collect the results from all the deferreds and pass them all back. The caller gets to figure out which values (if any) are errors.
* If no options are given (or `options.failOnFirstError` is `true`), `fail` will be called on the first error, as with `jQuery.when`. The value passed to `fail` will be an [index, value] list, to indicate which deferred was rejected.
* Any `.progress` callbacks added to the `when2` returned deferred are also called with `[index, value]` so you can tell which deferred made progress. Once the master deferred has fired, no further progress events are fired.
* `when2` always makes a new deferred (instead of trying to re-use the single deferred it is given if it only has one argument). This makes the code simpler and was in any case necessary due to needing to pass `[index, value]` values to the various callbacks.
* A slightly radical possible future thing to add would be to co-opt the `.progress` callback and use it to instead relay `resolve` info (each call having an index & a result to show which of the passed deferreds had resolved). A flag in `options` could request that behavior. It's a perversion but it's easy to think of ways in which that could be useful.
* It might be possible to implement `jQuery.when` in terms of `jQuery.when2`. I tried that originally, but ran into difficulty so decided to leave it for later (or never).
* It would be easy to add convenience functions like `jQuery.whenAnySuccess` or `jQuery.whenAllResolvedOrRejected` that just called `when2` with the correct option.

The aim here, obviously, is to provide more flexibility than `when` does. I don't like the name `when2` much, but I called it that for now (in the spirit of `dup2`). I'm sure my Javascript style wont match the jQuery style in some ways & am happy to fix that. I copied some of the `jQuery.when` tests, but some were too complicated to get right for `when2` so I ended up added a bunch of small tests as well.

Thanks for any help / discussion. I'm not expecting this to get merged anytime soon, or even at all. But I'd like to hear what people think.

BTW, the approach mirrors what you can do with Twisted's DeferredList (see http://twistedmatrix.com/documents/current/api/twisted.internet.defer.DeferredList.html), which gives you the same 3 behaviors: fire on first callback, fire on first errback, fire when everything is done (errors or not).