mirror of
https://github.com/jquery/jquery.git
synced 2025-01-10 18:24:24 +00:00
Deferred: syncronize single and multiple target handling in $.when
Fixes gh-2546 Fixes gh-2018 Close gh-2707
This commit is contained in:
parent
8b65446a60
commit
78b9eac119
@ -294,19 +294,17 @@ jQuery.extend( {
|
||||
},
|
||||
|
||||
// Deferred helper
|
||||
when: function( subordinate /* , ..., subordinateN */ ) {
|
||||
when: function() {
|
||||
var method,
|
||||
i = 0,
|
||||
resolveValues = slice.call( arguments ),
|
||||
length = resolveValues.length,
|
||||
|
||||
// the count of uncompleted subordinates
|
||||
remaining = length !== 1 ||
|
||||
( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,
|
||||
remaining = length,
|
||||
|
||||
// the master Deferred.
|
||||
// If resolveValues consist of only a single Deferred, just use that.
|
||||
master = remaining === 1 ? subordinate : jQuery.Deferred(),
|
||||
master = jQuery.Deferred(),
|
||||
|
||||
// Update function for both resolve and progress values
|
||||
updateFunc = function( i, contexts, values ) {
|
||||
@ -316,14 +314,17 @@ jQuery.extend( {
|
||||
if ( values === progressValues ) {
|
||||
master.notifyWith( contexts, values );
|
||||
} else if ( !( --remaining ) ) {
|
||||
master.resolveWith( contexts, values );
|
||||
master.resolveWith(
|
||||
contexts.length === 1 ? contexts[ 0 ] : contexts,
|
||||
values
|
||||
);
|
||||
}
|
||||
};
|
||||
},
|
||||
progressValues, progressContexts, resolveContexts;
|
||||
|
||||
// Add listeners to Deferred subordinates; treat others as resolved
|
||||
if ( length > 1 ) {
|
||||
if ( length > 0 ) {
|
||||
progressValues = new Array( length );
|
||||
progressContexts = new Array( length );
|
||||
resolveContexts = new Array( length );
|
||||
@ -345,14 +346,13 @@ jQuery.extend( {
|
||||
updateFunc( i, progressContexts, progressValues )
|
||||
);
|
||||
} else {
|
||||
--remaining;
|
||||
}
|
||||
updateFunc( i, resolveContexts, resolveValues )( resolveValues[ i ] );
|
||||
}
|
||||
}
|
||||
|
||||
// If we're not waiting on anything, resolve the master
|
||||
if ( !remaining ) {
|
||||
master.resolveWith( resolveContexts, resolveValues );
|
||||
} else {
|
||||
master.resolveWith();
|
||||
}
|
||||
|
||||
return master.promise();
|
||||
|
@ -667,7 +667,6 @@ QUnit.test( "jQuery.when", function( assert ) {
|
||||
"undefined": undefined,
|
||||
"a plain object": {},
|
||||
"an array": [ 1, 2, 3 ]
|
||||
|
||||
}, function( message, value ) {
|
||||
assert.ok(
|
||||
jQuery.isFunction(
|
||||
@ -698,12 +697,10 @@ QUnit.test( "jQuery.when", function( assert ) {
|
||||
} );
|
||||
|
||||
jQuery.each( [ 1, 2, 3 ], function( k, i ) {
|
||||
|
||||
jQuery.when( cache || jQuery.Deferred( function() {
|
||||
this.resolve( i );
|
||||
} )
|
||||
).done( function( value ) {
|
||||
|
||||
assert.strictEqual( value, 1, "Function executed" + ( i > 1 ? " only once" : "" ) );
|
||||
cache = value;
|
||||
} );
|
||||
@ -759,10 +756,8 @@ QUnit.test( "jQuery.when - joined", function( assert ) {
|
||||
expected = shouldResolve ? [ 1, 1 ] : [ 0, undefined ],
|
||||
expectedNotify = shouldNotify && [ willNotify[ id1 ], willNotify[ id2 ] ],
|
||||
code = "jQuery.when( " + id1 + ", " + id2 + " )",
|
||||
context1 = defer1 && jQuery.isFunction( defer1.promise ) ? defer1.promise() :
|
||||
( defer1.then ? window : undefined ),
|
||||
context2 = defer2 && jQuery.isFunction( defer2.promise ) ? defer2.promise() :
|
||||
( defer2.then ? window : undefined );
|
||||
context1 = defer1 && jQuery.isFunction( defer1.promise ) ? defer1.promise() : window,
|
||||
context2 = defer2 && jQuery.isFunction( defer2.promise ) ? defer2.promise() : window;
|
||||
|
||||
jQuery.when( defer1, defer2 ).done( function( a, b ) {
|
||||
if ( shouldResolve ) {
|
||||
@ -880,3 +875,36 @@ QUnit.test( "jQuery.when - chaining", function( assert ) {
|
||||
|
||||
defer.resolve( "other deferred" );
|
||||
} );
|
||||
|
||||
QUnit.test( "jQuery.when - solitary thenables", function( assert ) {
|
||||
|
||||
assert.expect( 1 );
|
||||
|
||||
var done = assert.async(),
|
||||
rejected = new Promise( function( resolve, reject ) {
|
||||
setTimeout( function() {
|
||||
reject( "rejected" );
|
||||
}, 100 );
|
||||
} );
|
||||
|
||||
jQuery.when( rejected ).then(
|
||||
function() {
|
||||
assert.ok( false, "Rejected, solitary, non-Deferred thenable should not resolve" );
|
||||
done();
|
||||
},
|
||||
function() {
|
||||
assert.ok( true, "Rejected, solitary, non-Deferred thenable rejected properly" );
|
||||
done();
|
||||
}
|
||||
);
|
||||
} );
|
||||
|
||||
QUnit.test( "jQuery.when does not reuse a solitary jQuery Deferred (gh-2018)", function( assert ) {
|
||||
|
||||
assert.expect( 2 );
|
||||
var defer = jQuery.Deferred().resolve(),
|
||||
promise = jQuery.when( defer );
|
||||
|
||||
assert.equal( promise.state(), "resolved", "Master Deferred is immediately resolved" );
|
||||
assert.notStrictEqual( defer.promise(), promise, "jQuery.when returns the master deferred's promise" );
|
||||
} );
|
||||
|
Loading…
Reference in New Issue
Block a user