Bug Tracker

Opened 7 years ago

Closed 7 years ago

Last modified 6 years ago

#12348 closed bug (worksforme)

$.when doesn't work as-documented?

Reported by: cowboy Owned by:
Priority: low Milestone: None
Component: ajax Version: 1.8.0
Keywords: Cc: jaubourg
Blocked by: Blocking:

Description

I see this text and example the docs:

If a single Deferred is passed to jQuery.when, its Promise object (a subset of the Deferred methods) is returned by the method. Additional methods of the Promise object can be called to attach callbacks, such as deferred.then. When the Deferred is resolved or rejected, usually by the code that created the Deferred originally, the appropriate callbacks will be called. For example, the jqXHR object returned by jQuery.ajax is a Deferred and can be used this way:

$.when( $.ajax("test.aspx") ).then(function(ajaxArgs){ 
     alert(ajaxArgs[1]); /* ajaxArgs is [ "success", statusText, jqXHR ] */
});

The thing is, when I pass a single jqXHR into $.when like in this fiddle:

​$.when( $.ajax(​"/echo/json/?a=1") ).then(function(ajaxArgs) {
    console.log(arguments.length, arguments);
});​​​​​​​​​​​

It logs 3 [Object, "success", Object], not [1 [Array]] Like I would expect, based on the example in the documentation. It seems like the array that the jqHXR is resolved with isn't passed into the .then callback as an array, but is instead applied onto the callback using .apply.

Also, the array in the example, [ "success", statusText, jqXHR ] is confusing. Maybe something more like [ response, statusText, jqXHR ]

Change History (5)

comment:1 Changed 7 years ago by cowboy

Part of the problem, that I see, is that because $.when is too smart for its own good, it sees a single jqXHR as a single Deferred.

And per the very first line in the docs, "If a single Deferred is passed to jQuery.when, its Promise object (a subset of the Deferred methods) is returned by the method, " it's assuming (incorrectly) that the single jqXHR is a Deferred wrapper around other deferreds, and thus applies the array the jqXHR is resolved with.

Basically, you should never pass in a single jqXHR into $.when.

comment:2 Changed 7 years ago by dmethvin

Cc: jaubourg added

You don't really need $.when for a single promise/deferred. I agree the example doesn't look right. Perhaps we need to included better reasoning there about why a single promise is treated specially.

comment:3 Changed 7 years ago by jaubourg

$.when is simply idempotent:

$.when( 1, 2, 3 ).done(function( a, b, c ) {
    a === 1;
    b === 2;
    c === 3;
});

$.when( $.when( $.when( 1, 2, 3 ) ) ).done(function( a, b, c ) {
    a === 1;
    b === 2;
    c === 3;
});

If it was to force every value into an array as was suggested in #10811, you would end up with:

$.when( $.when( $.when( 1, 2, 3 ) ) ).done(function( val ) {
    val = [ [ [ 1 ], [ 2 ], [ 3 ] ] ];
});

The single argument "passthru" ensures using $.when doesn't turn into a dereferencing nightmare.

I don't know why the doc is so, so wrong btw.

comment:4 Changed 7 years ago by dmethvin

Component: unfiledajax
Keywords: needsdocs added
Priority: undecidedlow
Resolution: worksforme
Status: newclosed

Here's the results of that example, slightly modified: http://jsfiddle.net/SAZY3/

But the description is fine, the example is just wrong.

comment:5 Changed 6 years ago by mikesherov

Keywords: needsdocs removed
Note: See TracTickets for help on using tickets.