Skip to main content

Bug Tracker

Side navigation

#12325 closed enhancement (wontfix)

Opened August 17, 2012 05:09AM UTC

Closed August 17, 2012 09:07AM UTC

Last modified August 17, 2012 09:23AM UTC

Options parameter for $.when() to provide alternative semantics

Reported by: hippietrail Owned by:
Priority: undecided Milestone: None
Component: unfiled Version: 1.8.0
Keywords: Cc:
Blocked by: Blocking:
Description

Currently $.when() has only one way of operating:

Wait until all Deferred's have been resolved ''or'' one has been rejected.

But there seem to be use cases for it to operate in other ways.

Some people want:

Wait until all Deferred's have been either resolved or rejected. (stackoverflow), (jquery bugs)

Others want:

Wait until one Deferred has been resolved. (stackoverflow), (stackoverflow)

And one more is:

Wait until all Deferred's have been rejected. (stackoverflow)

Do you see any merit in adding an "options" or "semantics" parameter to $.when() to allow the caller to specify these alternative behaviours? It could be as simple as this:

$.when( d1, d2, d3, {
  resolves: 'first',
  rejects: 'all'
}).then(
  // do stuff
);

(I guess you'd like to see a plugin first, but so far I'm not good enough at jQuery for that. In the meantime I'm interested in what others think of this proposal.)

Attachments (0)
Change History (2)

Changed August 17, 2012 09:07AM UTC by jaubourg comment:1

resolution: → wontfix
status: newclosed

There are several problems with this approach.

The first, most obvious, one is that you effectively forbid the use of when with an object that contains properties named resolves or rejects (when will promote such an object to a resolved Promise with the object itself as the resolve value).

So, if you want this new functionality, put it in a new helper.

The second one is a matter of semantics and predictability. I'll take your first example here: waiting when all deferred are either resolved or rejected.

How do you differentiate between resolve and rejection values when they are in the same arguments list?

$.whenResolvedOrRejected(
    $.Deferred().resolveWith( null, [ 1, 2, 3 ] ),
    $.Deferred().rejectWith( null, [ 4, 5, 6 ] )
).done(function( resolveValues, rejectValues ) {
    // How do I know what was resolved and what was rejected?
});

The only solution is to keep track of Deferreds in local variables:

var defer1 = $.Deferred().resolveWith( null, [ 1, 2, 3 ] ),
    defer2 = $.Deferred().rejectWith( null, [ 4, 5, 6 ] );

$.whenResolvedOrRejected( defer1, defer2 ).done(function( resolveValues, rejectValues ) {
    defer1.state() === "resolved";
    defer2.state() === "rejected";
});

That's simply an horrible approach.

To me, it's a typical case of Promise "re-routing":

function resolveAlways( promise ) {
    return promise.then(function() {
        return Deferred.resolveWith( this, [ "resolved" ].concat( arguments );
    }, function() {
        return Deferred.resolveWith( this, [ "rejected" ].concat( arguments );
    });
}

$.whenResolvedOrRejected(
    resolveAlways( $.Deferred().resolveWith( null, [ 1, 2, 3 ] ) ),
    resolveAlways( $.Deferred().rejectWith( null, [ 4, 5, 6 ] ) )
).done(function( resolveValues, rejectValues ) {
    resolveValues == [ "resolved", 1, 2, 3 ];
    rejectValues == [ "rejected", 4, 5, 6 ];
});

(I know arguments need to transformed into an array, but you get the idea)

Anyway, $.when is equivalent to a logical AND. I think that, if people need other kinds of operators, they should create new helpers, not mess with $.when to the point it doesn't make sense anymore.

I'd be glad to add such helpers into ajaxHooks ( https://github.com/jaubourg/ajaxHooks ), since adding new Promise helpers was my intention all along... except I just can't find the time to even maintain what's already in there :(

Changed August 17, 2012 09:23AM UTC by jaubourg comment:2

Ah, also, if you need more advanced/flexible synchros. You're probably better off with something like fence that'll abort non-completed ajax requests in case of rejection. See https://github.com/jaubourg/fence/blob/master/doc/intro.md#introduction-to-fence

Again, I still have to find time to write the damn API doc.