Skip to main content

Bug Tracker

Side navigation

#12348 closed bug (worksforme)

Opened August 19, 2012 07:01PM UTC

Closed August 20, 2012 11:48PM UTC

Last modified October 15, 2012 09:51PM UTC

$.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 ]

Attachments (0)
Change History (5)

Changed August 19, 2012 07:10PM UTC by cowboy comment:1

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.

Changed August 20, 2012 12:40AM UTC by dmethvin comment:2

cc: → jaubourg

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.

Changed August 20, 2012 08:03AM UTC by jaubourg comment:3

$.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.

Changed August 20, 2012 11:48PM UTC by dmethvin comment:4

component: unfiledajax
keywords: → needsdocs
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.

Changed October 15, 2012 09:51PM UTC by mikesherov comment:5

keywords: needsdocs