Deferred cannot be cancelled by returning false in a callback. Exception in the callback are still propagated and execution of remaining callbacks is still possible.
This commit is contained in:
parent
e3f3f18927
commit
846c52d1f8
79
src/core.js
79
src/core.js
|
@ -805,10 +805,7 @@ jQuery.extend({
|
|||
},
|
||||
|
||||
// Create a simple deferred (one callbacks list)
|
||||
_Deferred: function( cancellable ) {
|
||||
|
||||
// cancellable by default
|
||||
cancellable = cancellable !== false;
|
||||
_Deferred: function() {
|
||||
|
||||
var // callbacks list
|
||||
callbacks = [],
|
||||
|
@ -825,7 +822,7 @@ jQuery.extend({
|
|||
then: function () {
|
||||
|
||||
if ( ! cancelled ) {
|
||||
|
||||
|
||||
var args = arguments,
|
||||
i,
|
||||
length,
|
||||
|
@ -852,24 +849,23 @@ jQuery.extend({
|
|||
deferred.fire( _fired[ 0 ] , _fired[ 1 ] );
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
// resolve with given context and args
|
||||
// (i is used internally)
|
||||
fire: function( context , args , i ) {
|
||||
fire: function( context , args ) {
|
||||
if ( ! cancelled && ! fired && ! firing ) {
|
||||
|
||||
firing = 1;
|
||||
|
||||
try {
|
||||
for( i = 0 ; ! cancelled && callbacks[ i ] ; i++ ) {
|
||||
cancelled = ( callbacks[ i ].apply( context , args ) === false ) && cancellable;
|
||||
while( callbacks[ 0 ] ) {
|
||||
callbacks.shift().apply( context , args );
|
||||
}
|
||||
} catch( e ) {
|
||||
cancelled = cancellable;
|
||||
jQuery.error( e );
|
||||
} finally {
|
||||
}
|
||||
finally {
|
||||
fired = [ context , args ];
|
||||
callbacks = cancelled ? [] : callbacks.slice( i + 1 );
|
||||
firing = 0;
|
||||
}
|
||||
}
|
||||
|
@ -882,15 +878,22 @@ jQuery.extend({
|
|||
return this;
|
||||
},
|
||||
|
||||
// cancelling further callbacks
|
||||
cancel: function() {
|
||||
if ( cancellable ) {
|
||||
callbacks = [];
|
||||
cancelled = 1;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
// Has this deferred been resolved?
|
||||
isResolved: function() {
|
||||
return !!( firing || fired );
|
||||
},
|
||||
|
||||
// Cancel
|
||||
cancel: function() {
|
||||
cancelled = 1;
|
||||
callbacks = [];
|
||||
return this;
|
||||
},
|
||||
|
||||
// Has this deferred been cancelled?
|
||||
isCancelled: function() {
|
||||
return !!cancelled;
|
||||
}
|
||||
};
|
||||
|
||||
// Add the deferred marker
|
||||
|
@ -901,21 +904,11 @@ jQuery.extend({
|
|||
|
||||
// Full fledged deferred (two callbacks list)
|
||||
// Typical success/error system
|
||||
Deferred: function( func , cancellable ) {
|
||||
Deferred: function( func ) {
|
||||
|
||||
// Handle varargs
|
||||
if ( arguments.length === 1 ) {
|
||||
|
||||
if ( typeof func === "boolean" ) {
|
||||
cancellable = func;
|
||||
func = 0;
|
||||
}
|
||||
}
|
||||
|
||||
var errorDeferred = jQuery._Deferred( cancellable ),
|
||||
deferred = jQuery._Deferred( cancellable ),
|
||||
// Keep reference of the cancel method since we'll redefine it
|
||||
cancelThen = deferred.cancel;
|
||||
var errorDeferred = jQuery._Deferred(),
|
||||
deferred = jQuery._Deferred(),
|
||||
successCancel = deferred.cancel;
|
||||
|
||||
// Add errorDeferred methods and redefine cancel
|
||||
jQuery.extend( deferred , {
|
||||
|
@ -923,16 +916,16 @@ jQuery.extend({
|
|||
fail: errorDeferred.then,
|
||||
fireReject: errorDeferred.fire,
|
||||
reject: errorDeferred.resolve,
|
||||
cancel: function() {
|
||||
cancelThen();
|
||||
errorDeferred.cancel();
|
||||
return this;
|
||||
}
|
||||
isRejected: errorDeferred.isResolved
|
||||
|
||||
} );
|
||||
|
||||
// Remove cancel related
|
||||
delete deferred.cancel;
|
||||
delete deferred.isCancelled;
|
||||
|
||||
// Make sure only one callback list will be used
|
||||
deferred.then( errorDeferred.cancel ).fail( cancelThen );
|
||||
deferred.then( errorDeferred.cancel ).fail( successCancel );
|
||||
|
||||
// Call given func if any
|
||||
if ( func ) {
|
||||
|
@ -979,7 +972,7 @@ jQuery.extend({
|
|||
|
||||
// Create readyList deferred
|
||||
// also force $.fn.ready to be recognized as a defer
|
||||
readyList = jQuery._Deferred( false );
|
||||
readyList = jQuery._Deferred();
|
||||
jQuery.fn.ready._ = deferredMarker;
|
||||
|
||||
// Populate the class2type map
|
||||
|
|
|
@ -905,7 +905,7 @@ test("jQuery.parseJSON", function(){
|
|||
|
||||
test("jQuery._Deferred()", function() {
|
||||
|
||||
expect( 14 );
|
||||
expect( 10 );
|
||||
|
||||
var deferred,
|
||||
object,
|
||||
|
@ -938,31 +938,19 @@ test("jQuery._Deferred()", function() {
|
|||
test = true;
|
||||
|
||||
deferred.then( function() {
|
||||
ok( false , "Manual cancel was ignored" );
|
||||
ok( false , "Cancel was ignored" );
|
||||
test = false;
|
||||
} );
|
||||
|
||||
ok( test , "Test manual cancel" );
|
||||
ok( test , "Test cancel" );
|
||||
|
||||
deferred = jQuery._Deferred().then( function() {
|
||||
return false;
|
||||
} );
|
||||
deferred = jQuery._Deferred().resolve();
|
||||
|
||||
deferred.resolve();
|
||||
|
||||
test = true;
|
||||
|
||||
deferred.then( function() {
|
||||
test = false;
|
||||
} );
|
||||
|
||||
ok( test , "Test cancel by returning false" );
|
||||
|
||||
try {
|
||||
deferred = jQuery._Deferred().resolve().then( function() {
|
||||
deferred.then( function() {
|
||||
throw "Error";
|
||||
} , function() {
|
||||
ok( false , "Test deferred cancel on exception" );
|
||||
ok( true , "Test deferred do not cancel on exception" );
|
||||
} );
|
||||
} catch( e ) {
|
||||
strictEqual( e , "Error" , "Test deferred propagates exceptions");
|
||||
|
@ -1001,28 +989,6 @@ test("jQuery._Deferred()", function() {
|
|||
|
||||
strictEqual( test , "ABC" , "Test then callbacks order" );
|
||||
|
||||
deferred = jQuery._Deferred( false ).resolve().cancel();
|
||||
|
||||
deferred.then( function() {
|
||||
ok( true , "Test non-cancellable deferred not cancelled manually");
|
||||
return false;
|
||||
} );
|
||||
|
||||
deferred.then( function() {
|
||||
ok( true , "Test non-cancellable deferred not cancelled by returning false");
|
||||
} );
|
||||
|
||||
try {
|
||||
deferred.then( function() {
|
||||
throw "Error";
|
||||
} , function() {
|
||||
ok( true , "Test non-cancellable deferred keeps callbacks after exception" );
|
||||
} );
|
||||
} catch( e ) {
|
||||
strictEqual( e , "Error" , "Test non-cancellable deferred propagates exceptions");
|
||||
deferred.then();
|
||||
}
|
||||
|
||||
deferred = jQuery._Deferred();
|
||||
|
||||
deferred.fire( jQuery , [ document ] ).then( function( doc ) {
|
||||
|
@ -1032,7 +998,7 @@ test("jQuery._Deferred()", function() {
|
|||
|
||||
test("jQuery.Deferred()", function() {
|
||||
|
||||
expect( 8 );
|
||||
expect( 4 );
|
||||
|
||||
jQuery.Deferred( function( defer ) {
|
||||
strictEqual( this , defer , "Defer passed as this & first argument" );
|
||||
|
@ -1052,39 +1018,6 @@ test("jQuery.Deferred()", function() {
|
|||
}).fail( function() {
|
||||
ok( true , "Error on reject" );
|
||||
});
|
||||
|
||||
var flag = true;
|
||||
|
||||
jQuery.Deferred().resolve().cancel().then( function() {
|
||||
ok( flag = false , "Success on resolve/cancel" );
|
||||
}).fail( function() {
|
||||
ok( flag = false , "Error on resolve/cancel" );
|
||||
});
|
||||
|
||||
ok( flag , "Cancel on resolve" );
|
||||
|
||||
flag = true;
|
||||
|
||||
jQuery.Deferred().reject().cancel().then( function() {
|
||||
ok( flag = false , "Success on reject/cancel" );
|
||||
}).fail( function() {
|
||||
ok( flag = false , "Error on reject/cancel" );
|
||||
});
|
||||
|
||||
ok( flag , "Cancel on reject" );
|
||||
|
||||
jQuery.Deferred( false ).resolve().then( function() {
|
||||
return false;
|
||||
} , function() {
|
||||
ok( true , "Not cancelled on resolve" );
|
||||
});
|
||||
|
||||
jQuery.Deferred( false ).reject().fail( function() {
|
||||
return false;
|
||||
} , function() {
|
||||
ok( true , "Not cancelled on reject" );
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
test("jQuery.isDeferred()", function() {
|
||||
|
|
Loading…
Reference in a new issue