Trimmed down $.Callbacks and $.Deferred.

This commit is contained in:
jaubourg 2011-09-21 17:00:55 +02:00
parent 03d95530b5
commit a588336a6d
3 changed files with 34 additions and 78 deletions

View File

@ -20,9 +20,6 @@ function createFlags( flags ) {
* flags: an optional list of space-separated flags that will change how * flags: an optional list of space-separated flags that will change how
* the callback list behaves * the callback list behaves
* *
* filter: an optional function that will be applied to each added callbacks,
* what filter returns will then be added provided it is not falsy.
*
* By default a callback list will act like an event callback list and can be * By default a callback list will act like an event callback list and can be
* "fired" multiple times. * "fired" multiple times.
* *
@ -34,26 +31,12 @@ function createFlags( flags ) {
* after the list has been fired right away with the latest "memorized" * after the list has been fired right away with the latest "memorized"
* values (like a Deferred) * values (like a Deferred)
* *
* queue: only first callback in the list is called each time the list is fired
* (cannot be used in conjunction with memory)
*
* unique: will ensure a callback can only be added once (no duplicate in the list) * unique: will ensure a callback can only be added once (no duplicate in the list)
* *
* relocate: like "unique" but will relocate the callback at the end of the list
*
* stopOnFalse: interrupt callings when a callback returns false * stopOnFalse: interrupt callings when a callback returns false
* *
* addAfterFire: if callbacks are added while firing, then they are not executed until after
* the next call to fire/fireWith
*
*/ */
jQuery.Callbacks = function( flags, filter ) { jQuery.Callbacks = function( flags ) {
// flags are optional
if ( typeof flags !== "string" ) {
filter = flags;
flags = undefined;
}
// Convert flags from String-formatted to Object-formatted // Convert flags from String-formatted to Object-formatted
// (we check in cache first) // (we check in cache first)
@ -87,18 +70,9 @@ jQuery.Callbacks = function( flags, filter ) {
// Inspect recursively // Inspect recursively
add( elem ); add( elem );
} else if ( type === "function" ) { } else if ( type === "function" ) {
// If we have to relocate, we remove the callback // Add if not in unique mode and callback is not in
// if it already exists if ( !flags.unique || !self.has( elem ) ) {
if ( flags.relocate ) { list.push( elem );
self.remove( elem );
// Skip if we're in unique mode and callback is already in
} else if ( flags.unique && self.has( elem ) ) {
continue;
}
// Get the filtered function if needs be
actual = filter ? filter( elem ) : elem;
if ( actual ) {
list.push( [ elem, actual ] );
} }
} }
} }
@ -112,12 +86,9 @@ jQuery.Callbacks = function( flags, filter ) {
firingStart = 0; firingStart = 0;
firingLength = list.length; firingLength = list.length;
for ( ; list && firingIndex < firingLength; firingIndex++ ) { for ( ; list && firingIndex < firingLength; firingIndex++ ) {
if ( list[ firingIndex ][ 1 ].apply( context, args ) === false && flags.stopOnFalse ) { if ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) {
memory = true; // Mark as halted memory = true; // Mark as halted
break; break;
} else if ( flags.queue ) {
list.splice( firingIndex, 1 );
break;
} }
} }
firing = false; firing = false;
@ -144,9 +115,7 @@ jQuery.Callbacks = function( flags, filter ) {
// Do we need to add the callbacks to the // Do we need to add the callbacks to the
// current firing batch? // current firing batch?
if ( firing ) { if ( firing ) {
if ( !flags.addAfterFire ) { firingLength = list.length;
firingLength = list.length;
}
// With memory, if we're not firing then // With memory, if we're not firing then
// we should call right away, unless previous // we should call right away, unless previous
// firing was halted (stopOnFalse) // firing was halted (stopOnFalse)
@ -165,7 +134,7 @@ jQuery.Callbacks = function( flags, filter ) {
argLength = args.length; argLength = args.length;
for ( ; argIndex < argLength ; argIndex++ ) { for ( ; argIndex < argLength ; argIndex++ ) {
for ( var i = 0; i < list.length; i++ ) { for ( var i = 0; i < list.length; i++ ) {
if ( args[ argIndex ] === list[ i ][ 0 ] ) { if ( args[ argIndex ] === list[ i ] ) {
// Handle firingIndex and firingLength // Handle firingIndex and firingLength
if ( firing ) { if ( firing ) {
if ( i <= firingLength ) { if ( i <= firingLength ) {
@ -179,7 +148,7 @@ jQuery.Callbacks = function( flags, filter ) {
list.splice( i--, 1 ); list.splice( i--, 1 );
// If we have some unicity property then // If we have some unicity property then
// we only need to do this once // we only need to do this once
if ( flags.unique || flags.relocate ) { if ( flags.unique ) {
break; break;
} }
} }
@ -194,7 +163,7 @@ jQuery.Callbacks = function( flags, filter ) {
var i = 0, var i = 0,
length = list.length; length = list.length;
for ( ; i < length; i++ ) { for ( ; i < length; i++ ) {
if ( fn === list[ i ][ 0 ] ) { if ( fn === list[ i ] ) {
return true; return true;
} }
} }

View File

@ -1,8 +1,6 @@
(function( jQuery ) { (function( jQuery ) {
var // Promise methods var // Static reference to slice
promiseMethods = "done removeDone fail removeFail progress removeProgress isResolved isRejected promise then always pipe".split( " " ),
// Static reference to slice
sliceDeferred = [].slice; sliceDeferred = [].slice;
jQuery.extend({ jQuery.extend({
@ -11,31 +9,28 @@ jQuery.extend({
var doneList = jQuery.Callbacks( "once memory" ), var doneList = jQuery.Callbacks( "once memory" ),
failList = jQuery.Callbacks( "once memory" ), failList = jQuery.Callbacks( "once memory" ),
progressList = jQuery.Callbacks( "memory" ), progressList = jQuery.Callbacks( "memory" ),
promise, lists = {
deferred = { resolve: doneList,
// Copy existing methods from lists reject: failList,
notify: progressList
},
promise = {
done: doneList.add, done: doneList.add,
removeDone: doneList.remove,
fail: failList.add, fail: failList.add,
removeFail: failList.remove,
progress: progressList.add, progress: progressList.add,
removeProgress: progressList.remove,
resolve: doneList.fire,
resolveWith: doneList.fireWith,
reject: failList.fire,
rejectWith: failList.fireWith,
notify: progressList.fire,
notifyWith: progressList.fireWith,
isResolved: doneList.fired, isResolved: doneList.fired,
isRejected: failList.fired, isRejected: failList.fired,
isProgressing: function() {
return !progressList.locked();
},
// Create Deferred-specific methods
then: function( doneCallbacks, failCallbacks, progressCallbacks ) { then: function( doneCallbacks, failCallbacks, progressCallbacks ) {
deferred.done( doneCallbacks ).fail( failCallbacks ).progress( progressCallbacks ); deferred.done( doneCallbacks ).fail( failCallbacks ).progress( progressCallbacks );
return this; return this;
}, },
always: function() { always: function() {
return deferred.done.apply( deferred, arguments ).fail.apply( this, arguments ); return deferred.done.apply( deferred, arguments ).fail.apply( deferred, arguments );
}, },
pipe: function( fnDone, fnFail, fnProgress ) { pipe: function( fnDone, fnFail, fnProgress ) {
return jQuery.Deferred(function( newDefer ) { return jQuery.Deferred(function( newDefer ) {
@ -66,18 +61,22 @@ jQuery.extend({
// If obj is provided, the promise aspect is added to the object // If obj is provided, the promise aspect is added to the object
promise: function( obj ) { promise: function( obj ) {
if ( obj == null ) { if ( obj == null ) {
if ( promise ) { obj = promise;
return promise; } else {
for( var key in promise ) {
obj[ key ] = promise[ key ];
} }
promise = obj = {};
}
var i = promiseMethods.length;
while( i-- ) {
obj[ promiseMethods[i] ] = deferred[ promiseMethods[i] ];
} }
return obj; return obj;
} }
}; },
deferred = promise.promise({}),
key;
for ( key in lists ) {
deferred[ key ] = lists[ key ].fire;
deferred[ key + "With" ] = lists[ key ].fireWith;
}
// Handle lists exclusiveness // Handle lists exclusiveness
deferred.done( failList.disable, progressList.lock ) deferred.done( failList.disable, progressList.lock )

View File

@ -16,25 +16,13 @@ var output,
"once": "XABC X X X X X XABA X", "once": "XABC X X X X X XABA X",
"memory": "XABC XABC XABCABCCC XA XBB XB XABA XC", "memory": "XABC XABC XABCABCCC XA XBB XB XABA XC",
"unique": "XABC X XABCA X XBB X XAB X", "unique": "XABC X XABCA X XBB X XAB X",
"relocate": "XABC X XAABC X XBB X XBA X",
"stopOnFalse": "XABC X XABCABCC X XBB X XA X", "stopOnFalse": "XABC X XABCABCC X XBB X XA X",
"addAfterFire": "XAB X XABCAB X XBB X XABA X",
"queue": "XA X XB X XB X XA X",
"once memory": "XABC XABC X XA X XA XABA XC", "once memory": "XABC XABC X XA X XA XABA XC",
"once unique": "XABC X X X X X XAB X", "once unique": "XABC X X X X X XAB X",
"once relocate": "XABC X X X X X XBA X",
"once stopOnFalse": "XABC X X X X X XA X", "once stopOnFalse": "XABC X X X X X XA X",
"once addAfterFire": "XAB X X X X X XABA X",
"memory unique": "XABC XA XABCA XA XBB XB XAB XC", "memory unique": "XABC XA XABCA XA XBB XB XAB XC",
"memory relocate": "XABC XB XAABC XA XBB XB XBA XC",
"memory stopOnFalse": "XABC XABC XABCABCCC XA XBB XB XA X", "memory stopOnFalse": "XABC XABC XABCABCCC XA XBB XB XA X",
"memory addAfterFire": "XAB XAB XABCABC XA XBB XB XABA XC", "unique stopOnFalse": "XABC X XABCA X XBB X XA X"
"unique relocate": "XABC X XAABC X XBB X XBA X",
"unique stopOnFalse": "XABC X XABCA X XBB X XA X",
"unique addAfterFire": "XAB X XABCA X XBB X XAB X",
"relocate stopOnFalse": "XABC X XAABC X XBB X X X",
"relocate addAfterFire": "XAB X XAA X XBB X XBA X",
"stopOnFalse addAfterFire": "XAB X XABCAB X XBB X XA X"
}, },
filters = { filters = {
"no filter": undefined, "no filter": undefined,