// Forget the data if we're done with it
// Clean up if we're done firing for good
// Keep an empty list if we have data for future add calls
// Otherwise, this object is spent
// Actual Callbacks object
// Add a callback or a collection of callbacks to the list
// If we have memory from a past run, we should fire after adding
if ( memory && !firing ) {
firingIndex = list.length - 1;
jQuery.each( args, function( _, arg ) {
if ( isFunction( arg ) ) {
if ( !options.unique || !self.has( arg ) ) {
} else if ( arg && arg.length && toType( arg ) !== "string" ) {
if ( memory && !firing ) {
// Remove a callback from the list
jQuery.each( arguments, function( _, arg ) {
while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
if ( index <= firingIndex ) {
// Check if a given callback is in the list.
// If no argument is given, return whether or not list has callbacks attached.
jQuery.inArray( fn, list ) > -1 :
// Remove all callbacks from the list
// Disable .fire and .add
// Abort any current/pending executions
// Clear all callbacks and values
// Also disable .add unless we have memory (since it would have no effect)
// Abort any pending executions
if ( !memory && !firing ) {
// Call all callbacks with the given context and arguments
fireWith: function( context, args ) {
args = [ context, args.slice ? args.slice() : args ];
// Call all the callbacks with the given arguments
self.fireWith( this, arguments );
// To know if the callbacks have already been called at least once
function adoptValue( value, resolve, reject, noValue ) {
// Check for promise aspect first to privilege synchronous behavior
if ( value && isFunction( ( method = value.promise ) ) ) {
method.call( value ).done( resolve ).fail( reject );
} else if ( value && isFunction( ( method = value.then ) ) ) {
method.call( value, resolve, reject );
// Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer:
// * false: [ value ].slice( 0 ) => resolve( value )
// * true: [ value ].slice( 1 ) => resolve()
resolve.apply( undefined, [ value ].slice( noValue ) );
// For Promises/A+, convert exceptions into rejections
// Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in
// Deferred#then to conditionally suppress rejection.
// Support: Android 4.0 only
// Strict mode functions invoked without .call/.apply get global-object context
reject.apply( undefined, [ value ] );
Deferred: function( func ) {
// action, add listener, callbacks,
// ... .then handlers, argument index, [final state]
[ "notify", "progress", jQuery.Callbacks( "memory" ),
jQuery.Callbacks( "memory" ), 2 ],
[ "resolve", "done", jQuery.Callbacks( "once memory" ),
jQuery.Callbacks( "once memory" ), 0, "resolved" ],
[ "reject", "fail", jQuery.Callbacks( "once memory" ),
jQuery.Callbacks( "once memory" ), 1, "rejected" ]
deferred.done( arguments ).fail( arguments );
"catch": function( fn ) {
return promise.then( null, fn );
// Keep pipe for back-compat
pipe: function( /* fnDone, fnFail, fnProgress */ ) {
return jQuery.Deferred( function( newDefer ) {
jQuery.each( tuples, function( _i, tuple ) {
// Map tuples (progress, done, fail) to arguments (done, fail, progress)
var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ];
// deferred.progress(function() { bind to newDefer or newDefer.notify })
// deferred.done(function() { bind to newDefer or newDefer.resolve })
// deferred.fail(function() { bind to newDefer or newDefer.reject })
deferred[ tuple[ 1 ] ]( function() {
var returned = fn && fn.apply( this, arguments );
if ( returned && isFunction( returned.promise ) ) {
.progress( newDefer.notify )
.done( newDefer.resolve )
.fail( newDefer.reject );
newDefer[ tuple[ 0 ] + "With" ](
fn ? [ returned ] : arguments
then: function( onFulfilled, onRejected, onProgress ) {
function resolve( depth, deferred, handler, special ) {
mightThrow = function() {
// Support: Promises/A+ section 2.3.3.3.3
// https://promisesaplus.com/#point-59
// Ignore double-resolution attempts
if ( depth < maxDepth ) {
returned = handler.apply( that, args );
// Support: Promises/A+ section 2.3.1
// https://promisesaplus.com/#point-48
if ( returned === deferred.promise() ) {
throw new TypeError( "Thenable self-resolution" );
// Support: Promises/A+ sections 2.3.3.1, 3.5
// https://promisesaplus.com/#point-54
// https://promisesaplus.com/#point-75
// Retrieve `then` only once
// Support: Promises/A+ section 2.3.4
// https://promisesaplus.com/#point-64
// Only check objects and functions for thenability
( typeof returned === "object" ||
typeof returned === "function" ) &&
// Handle a returned thenable
if ( isFunction( then ) ) {
// Special processors (notify) just wait for resolution
resolve( maxDepth, deferred, Identity, special ),
resolve( maxDepth, deferred, Thrower, special )
// Normal processors (resolve) also hook into progress
// ...and disregard older resolution values
resolve( maxDepth, deferred, Identity, special ),
resolve( maxDepth, deferred, Thrower, special ),
resolve( maxDepth, deferred, Identity,
// Handle all other returned values
// Only substitute handlers pass on context
// and multiple values (non-spec behavior)
if ( handler !== Identity ) {
// Default process is resolve
( special || deferred.resolveWith )( that, args );
// Only normal processors (resolve) catch and reject exceptions
if ( jQuery.Deferred.exceptionHook ) {
jQuery.Deferred.exceptionHook( e,
// Support: Promises/A+ section 2.3.3.3.4.1
// https://promisesaplus.com/#point-61
// Ignore post-resolution exceptions
if ( depth + 1 >= maxDepth ) {
// Only substitute handlers pass on context
// and multiple values (non-spec behavior)
if ( handler !== Thrower ) {
deferred.rejectWith( that, args );
// Support: Promises/A+ section 2.3.3.3.1
// https://promisesaplus.com/#point-57
// Re-resolve promises immediately to dodge false rejection from
// Call an optional hook to record the stack, in case of exception
// since it's otherwise lost when execution goes async
if ( jQuery.Deferred.getStackHook ) {
process.stackTrace = jQuery.Deferred.getStackHook();
window.setTimeout( process );
return jQuery.Deferred( function( newDefer ) {
// progress_handlers.add( ... )
isFunction( onProgress ) ?
// fulfilled_handlers.add( ... )
isFunction( onFulfilled ) ?
// rejected_handlers.add( ... )
isFunction( onRejected ) ?
// Get a promise for this deferred
// If obj is provided, the promise aspect is added to the object
promise: function( obj ) {
return obj != null ? jQuery.extend( obj, promise ) : promise;
// Add list-specific methods
jQuery.each( tuples, function( i, tuple ) {
stateString = tuple[ 5 ];
// promise.progress = list.add
// promise.done = list.add
// promise.fail = list.add
promise[ tuple[ 1 ] ] = list.add;
// state = "resolved" (i.e., fulfilled)
// rejected_callbacks.disable
// fulfilled_callbacks.disable
tuples[ 3 - i ][ 2 ].disable,
// rejected_handlers.disable
// fulfilled_handlers.disable
tuples[ 3 - i ][ 3 ].disable,
// progress_callbacks.lock
// progress_handlers.lock
// progress_handlers.fire
// fulfilled_handlers.fire
// rejected_handlers.fire
list.add( tuple[ 3 ].fire );
// deferred.notify = function() { deferred.notifyWith(...) }
// deferred.resolve = function() { deferred.resolveWith(...) }
// deferred.reject = function() { deferred.rejectWith(...) }
deferred[ tuple[ 0 ] ] = function() {
deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments );
// deferred.notifyWith = list.fireWith
// deferred.resolveWith = list.fireWith
// deferred.rejectWith = list.fireWith
deferred[ tuple[ 0 ] + "With" ] = list.fireWith;
// Make the deferred a promise
promise.promise( deferred );
// Call given func if any
func.call( deferred, deferred );
when: function( singleValue ) {
// count of uncompleted subordinates
remaining = arguments.length,
// count of unprocessed arguments
// subordinate fulfillment data
resolveContexts = Array( i ),
resolveValues = slice.call( arguments ),