forked from jquery/jquery
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Moves Deferred-related code into a separate module. Context handling …
…has been simplified in _Deferred.resolve and jQuery.when has been refactored for clarity (and minor optimization).
- Loading branch information
Showing
17 changed files
with
407 additions
and
393 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
(function( jQuery ) { | ||
|
||
var // Promise methods | ||
promiseMethods = "then done fail isResolved isRejected promise".split( " " ), | ||
// Static reference to slice | ||
sliceDeferred = [].slice; | ||
|
||
jQuery.extend({ | ||
// Create a simple deferred (one callbacks list) | ||
_Deferred: function() { | ||
var // callbacks list | ||
callbacks = [], | ||
// stored [ context , args ] | ||
fired, | ||
// to avoid firing when already doing so | ||
firing, | ||
// flag to know if the deferred has been cancelled | ||
cancelled, | ||
// the deferred itself | ||
deferred = { | ||
|
||
// done( f1, f2, ...) | ||
done: function() { | ||
if ( !cancelled ) { | ||
var args = arguments, | ||
i, | ||
length, | ||
elem, | ||
type, | ||
_fired; | ||
if ( fired ) { | ||
_fired = fired; | ||
fired = 0; | ||
} | ||
for ( i = 0, length = args.length; i < length; i++ ) { | ||
elem = args[ i ]; | ||
type = jQuery.type( elem ); | ||
if ( type === "array" ) { | ||
deferred.done.apply( deferred, elem ); | ||
} else if ( type === "function" ) { | ||
callbacks.push( elem ); | ||
} | ||
} | ||
if ( _fired ) { | ||
deferred.resolveWith( _fired[ 0 ], _fired[ 1 ] ); | ||
} | ||
} | ||
return this; | ||
}, | ||
|
||
// resolve with given context and args | ||
resolveWith: function( context, args ) { | ||
if ( !cancelled && !fired && !firing ) { | ||
// make sure args are available (#8421) | ||
args = args || []; | ||
firing = 1; | ||
try { | ||
while( callbacks[ 0 ] ) { | ||
callbacks.shift().apply( context, args ); | ||
} | ||
} | ||
finally { | ||
fired = [ context, args ]; | ||
firing = 0; | ||
} | ||
} | ||
return this; | ||
}, | ||
|
||
// resolve with this as context and given arguments | ||
resolve: function() { | ||
deferred.resolveWith( this, arguments ); | ||
return this; | ||
}, | ||
|
||
// Has this deferred been resolved? | ||
isResolved: function() { | ||
return !!( firing || fired ); | ||
}, | ||
|
||
// Cancel | ||
cancel: function() { | ||
cancelled = 1; | ||
callbacks = []; | ||
return this; | ||
} | ||
}; | ||
|
||
return deferred; | ||
}, | ||
|
||
// Full fledged deferred (two callbacks list) | ||
Deferred: function( func ) { | ||
var deferred = jQuery._Deferred(), | ||
failDeferred = jQuery._Deferred(), | ||
promise; | ||
// Add errorDeferred methods, then and promise | ||
jQuery.extend( deferred, { | ||
then: function( doneCallbacks, failCallbacks ) { | ||
deferred.done( doneCallbacks ).fail( failCallbacks ); | ||
return this; | ||
}, | ||
fail: failDeferred.done, | ||
rejectWith: failDeferred.resolveWith, | ||
reject: failDeferred.resolve, | ||
isRejected: failDeferred.isResolved, | ||
// Get a promise for this deferred | ||
// If obj is provided, the promise aspect is added to the object | ||
promise: function( obj ) { | ||
if ( obj == null ) { | ||
if ( promise ) { | ||
return promise; | ||
} | ||
promise = obj = {}; | ||
} | ||
var i = promiseMethods.length; | ||
while( i-- ) { | ||
obj[ promiseMethods[i] ] = deferred[ promiseMethods[i] ]; | ||
} | ||
return obj; | ||
} | ||
} ); | ||
// Make sure only one callback list will be used | ||
deferred.done( failDeferred.cancel ).fail( deferred.cancel ); | ||
// Unexpose cancel | ||
delete deferred.cancel; | ||
// Call given func if any | ||
if ( func ) { | ||
func.call( deferred, deferred ); | ||
} | ||
return deferred; | ||
}, | ||
|
||
// Deferred helper | ||
when: function( firstParam ) { | ||
var args = arguments, | ||
i = 0, | ||
length = args.length, | ||
count = length, | ||
deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ? | ||
firstParam : | ||
jQuery.Deferred(); | ||
function resolveFunc( i ) { | ||
return function( value ) { | ||
args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value; | ||
if ( !( --count ) ) { | ||
deferred.resolveWith( deferred, args ); | ||
} | ||
}; | ||
} | ||
if ( length > 1 ) { | ||
for( ; i < length; i++ ) { | ||
if ( args[ i ] && jQuery.isFunction( args[ i ].promise ) ) { | ||
args[ i ].promise().then( resolveFunc(i), deferred.reject ); | ||
} else { | ||
--count; | ||
} | ||
} | ||
if ( !count ) { | ||
deferred.resolveWith( deferred, args ); | ||
} | ||
} else if ( deferred !== firstParam ) { | ||
deferred.resolveWith( deferred, length ? [ firstParam ] : [] ); | ||
} | ||
return deferred.promise(); | ||
} | ||
}); | ||
|
||
})( jQuery ); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.