Added deferred to core. Used internally for DOM readyness and ajax callbacks.
This commit is contained in:
parent
291b1edf44
commit
88d97deb77
208
src/core.js
208
src/core.js
|
@ -60,8 +60,8 @@ var jQuery = function( selector, context ) {
|
||||||
// Has the ready events already been bound?
|
// Has the ready events already been bound?
|
||||||
readyBound = false,
|
readyBound = false,
|
||||||
|
|
||||||
// The functions to execute on DOM ready
|
// The deferred used on DOM ready
|
||||||
readyList = [],
|
readyList,
|
||||||
|
|
||||||
// The ready event handler
|
// The ready event handler
|
||||||
DOMContentLoaded,
|
DOMContentLoaded,
|
||||||
|
@ -75,7 +75,10 @@ var jQuery = function( selector, context ) {
|
||||||
indexOf = Array.prototype.indexOf,
|
indexOf = Array.prototype.indexOf,
|
||||||
|
|
||||||
// [[Class]] -> type pairs
|
// [[Class]] -> type pairs
|
||||||
class2type = {};
|
class2type = {},
|
||||||
|
|
||||||
|
// Marker for deferred
|
||||||
|
deferredMarker = [];
|
||||||
|
|
||||||
jQuery.fn = jQuery.prototype = {
|
jQuery.fn = jQuery.prototype = {
|
||||||
init: function( selector, context ) {
|
init: function( selector, context ) {
|
||||||
|
@ -253,22 +256,12 @@ jQuery.fn = jQuery.prototype = {
|
||||||
return jQuery.each( this, callback, args );
|
return jQuery.each( this, callback, args );
|
||||||
},
|
},
|
||||||
|
|
||||||
ready: function( fn ) {
|
ready: function() {
|
||||||
// Attach the listeners
|
// Attach the listeners
|
||||||
jQuery.bindReady();
|
jQuery.bindReady();
|
||||||
|
|
||||||
// If the DOM is already ready
|
// Change ready & apply
|
||||||
if ( jQuery.isReady ) {
|
return ( jQuery.fn.ready = readyList.then ).apply( this , arguments );
|
||||||
// Execute the function immediately
|
|
||||||
fn.call( document, jQuery );
|
|
||||||
|
|
||||||
// Otherwise, remember the function for later
|
|
||||||
} else if ( readyList ) {
|
|
||||||
// Add the function to the wait list
|
|
||||||
readyList.push( fn );
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
eq: function( i ) {
|
eq: function( i ) {
|
||||||
|
@ -415,23 +408,11 @@ jQuery.extend({
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there are functions bound, to execute
|
// If there are functions bound, to execute
|
||||||
if ( readyList ) {
|
readyList.fire( document , [ jQuery ] );
|
||||||
// Execute all of them
|
|
||||||
var fn,
|
// Trigger any bound ready events
|
||||||
i = 0,
|
if ( jQuery.fn.trigger ) {
|
||||||
ready = readyList;
|
jQuery( document ).trigger( "ready" ).unbind( "ready" );
|
||||||
|
|
||||||
// Reset the list of functions
|
|
||||||
readyList = null;
|
|
||||||
|
|
||||||
while ( (fn = ready[ i++ ]) ) {
|
|
||||||
fn.call( document, jQuery );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Trigger any bound ready events
|
|
||||||
if ( jQuery.fn.trigger ) {
|
|
||||||
jQuery( document ).trigger( "ready" ).unbind( "ready" );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -800,6 +781,160 @@ jQuery.extend({
|
||||||
now: function() {
|
now: function() {
|
||||||
return (new Date()).getTime();
|
return (new Date()).getTime();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Create a simple deferred (one callbacks list)
|
||||||
|
_deferred: function( cancellable ) {
|
||||||
|
|
||||||
|
// cancellable by default
|
||||||
|
cancellable = cancellable !== false;
|
||||||
|
|
||||||
|
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 = {
|
||||||
|
|
||||||
|
// then( f1, f2, ...)
|
||||||
|
then: function() {
|
||||||
|
|
||||||
|
if ( ! cancelled ) {
|
||||||
|
|
||||||
|
var args = arguments,
|
||||||
|
i,
|
||||||
|
type,
|
||||||
|
_fired;
|
||||||
|
|
||||||
|
if ( fired ) {
|
||||||
|
_fired = fired;
|
||||||
|
fired = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( i in args ) {
|
||||||
|
i = args[ i ];
|
||||||
|
type = jQuery.type( i );
|
||||||
|
if ( type === "array" ) {
|
||||||
|
this.then.apply( this , i );
|
||||||
|
} else if ( type === "function" ) {
|
||||||
|
callbacks.push( i );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( _fired ) {
|
||||||
|
deferred.fire( _fired[ 0 ] , _fired[ 1 ] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
// resolve with given context and args
|
||||||
|
// (i is used internally)
|
||||||
|
fire: function( context , args , i ) {
|
||||||
|
if ( ! cancelled && ! fired && ! firing ) {
|
||||||
|
firing = 1;
|
||||||
|
try {
|
||||||
|
for( i = 0 ; ! cancelled && callbacks[ i ] ; i++ ) {
|
||||||
|
cancelled = ( callbacks[ i ].apply( context , args ) === false ) && cancellable;
|
||||||
|
}
|
||||||
|
} catch( e ) {
|
||||||
|
cancelled = cancellable;
|
||||||
|
jQuery.error( e );
|
||||||
|
} finally {
|
||||||
|
fired = [ context , args ];
|
||||||
|
callbacks = cancelled ? [] : callbacks.slice( i + 1 );
|
||||||
|
firing = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
// resolve with this as context and given arguments
|
||||||
|
resolve: function() {
|
||||||
|
deferred.fire( this , arguments );
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
// cancelling further callbacks
|
||||||
|
cancel: function() {
|
||||||
|
if ( cancellable ) {
|
||||||
|
callbacks = [];
|
||||||
|
cancelled = 1;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add the deferred marker
|
||||||
|
deferred.then._ = deferredMarker;
|
||||||
|
|
||||||
|
return deferred;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Full fledged deferred (two callbacks list)
|
||||||
|
// Typical success/error system
|
||||||
|
deferred: function( func , cancellable ) {
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
// Add errorDeferred methods and redefine cancel
|
||||||
|
jQuery.extend( deferred , {
|
||||||
|
|
||||||
|
fail: errorDeferred.then,
|
||||||
|
fireReject: errorDeferred.fire,
|
||||||
|
reject: errorDeferred.resolve,
|
||||||
|
cancel: function() {
|
||||||
|
cancelThen();
|
||||||
|
errorDeferred.cancel();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
} );
|
||||||
|
|
||||||
|
// Make sure only one callback list will be used
|
||||||
|
deferred.then( errorDeferred.cancel ).fail( cancelThen );
|
||||||
|
|
||||||
|
// Call given func if any
|
||||||
|
if ( func ) {
|
||||||
|
func.call( deferred , deferred );
|
||||||
|
}
|
||||||
|
|
||||||
|
return deferred;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Check if an object is a deferred
|
||||||
|
isDeferred: function( object , method ) {
|
||||||
|
method = method || "then";
|
||||||
|
return !!( object && object[ method ] && object[ method ]._ === deferredMarker );
|
||||||
|
},
|
||||||
|
|
||||||
|
// Deferred helper
|
||||||
|
when: function( object , method ) {
|
||||||
|
method = method || "then";
|
||||||
|
object = jQuery.isDeferred( object , method ) ?
|
||||||
|
object :
|
||||||
|
jQuery.deferred().resolve( object );
|
||||||
|
object.fail = object.fail || function() { return this; };
|
||||||
|
object[ method ] = object[ method ] || object.then;
|
||||||
|
object.then = object.then || object[ method ];
|
||||||
|
return object;
|
||||||
|
},
|
||||||
|
|
||||||
// Use of jQuery.browser is frowned upon.
|
// Use of jQuery.browser is frowned upon.
|
||||||
// More details: http://docs.jquery.com/Utilities/jQuery.browser
|
// More details: http://docs.jquery.com/Utilities/jQuery.browser
|
||||||
|
@ -818,6 +953,11 @@ jQuery.extend({
|
||||||
browser: {}
|
browser: {}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Create readyList deferred
|
||||||
|
// also force $.fn.ready to be recognized as a defer
|
||||||
|
readyList = jQuery._deferred( false );
|
||||||
|
jQuery.fn.ready._ = deferredMarker;
|
||||||
|
|
||||||
// Populate the class2type map
|
// Populate the class2type map
|
||||||
jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {
|
jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {
|
||||||
class2type[ "[object " + name + "]" ] = name.toLowerCase();
|
class2type[ "[object " + name + "]" ] = name.toLowerCase();
|
||||||
|
|
171
src/xhr.js
171
src/xhr.js
|
@ -18,18 +18,19 @@ jQuery.xhr = function( _native ) {
|
||||||
return jQuery.ajaxSettings.xhr();
|
return jQuery.ajaxSettings.xhr();
|
||||||
}
|
}
|
||||||
|
|
||||||
function reset(force) {
|
function reset( force ) {
|
||||||
|
|
||||||
// We only need to reset if we went through the init phase
|
// We only need to reset if we went through the init phase
|
||||||
// (with the exception of object creation)
|
// (with the exception of object creation)
|
||||||
if ( force || internal ) {
|
if ( force || internal ) {
|
||||||
|
|
||||||
// Reset callbacks lists
|
// Reset callbacks lists
|
||||||
callbacksLists = {
|
deferred = jQuery.deferred();
|
||||||
success: createCBList(),
|
completeDeferred = jQuery._deferred();
|
||||||
error: createCBList(),
|
|
||||||
complete: createCBList()
|
xhr.success = xhr.then = deferred.then;
|
||||||
};
|
xhr.error = xhr.fail = deferred.fail;
|
||||||
|
xhr.complete = completeDeferred.then;
|
||||||
|
|
||||||
// Reset private variables
|
// Reset private variables
|
||||||
requestHeaders = {};
|
requestHeaders = {};
|
||||||
|
@ -155,8 +156,8 @@ jQuery.xhr = function( _native ) {
|
||||||
callbackContext = s.context || s;
|
callbackContext = s.context || s;
|
||||||
globalEventContext = s.context ? jQuery(s.context) : jQuery.event;
|
globalEventContext = s.context ? jQuery(s.context) : jQuery.event;
|
||||||
|
|
||||||
for ( i in callbacksLists ) {
|
for ( i in { success:1, error:1, complete:1 } ) {
|
||||||
callbacksLists[i].bind(s[i]);
|
xhr[ i ]( s[ i ] );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Watch for a new set of requests
|
// Watch for a new set of requests
|
||||||
|
@ -355,10 +356,12 @@ jQuery.xhr = function( _native ) {
|
||||||
|
|
||||||
// Keep local copies of vars in case callbacks re-use the xhr
|
// Keep local copies of vars in case callbacks re-use the xhr
|
||||||
var _s = s,
|
var _s = s,
|
||||||
_callbacksLists = callbacksLists,
|
_deferred = deferred,
|
||||||
|
_completeDeferred = completeDeferred,
|
||||||
_callbackContext = callbackContext,
|
_callbackContext = callbackContext,
|
||||||
_globalEventContext = globalEventContext;
|
_globalEventContext = globalEventContext;
|
||||||
|
|
||||||
|
|
||||||
// Set state if the xhr hasn't been re-used
|
// Set state if the xhr hasn't been re-used
|
||||||
function _setState( value ) {
|
function _setState( value ) {
|
||||||
if ( xhr.readyState && s === _s ) {
|
if ( xhr.readyState && s === _s ) {
|
||||||
|
@ -375,18 +378,20 @@ jQuery.xhr = function( _native ) {
|
||||||
// We're done
|
// We're done
|
||||||
_setState( 4 );
|
_setState( 4 );
|
||||||
|
|
||||||
// Success
|
// Success/Error
|
||||||
_callbacksLists.success.fire( isSuccess , _callbackContext , success, statusText, xhr);
|
if ( isSuccess ) {
|
||||||
if ( isSuccess && _s.global ) {
|
_deferred.fire( _callbackContext , [ success , statusText , xhr ] );
|
||||||
_globalEventContext.trigger( "ajaxSuccess", [xhr, _s, success] );
|
} else {
|
||||||
|
_deferred.fireReject( _callbackContext , [ xhr , statusText , error ] );
|
||||||
}
|
}
|
||||||
// Error
|
|
||||||
_callbacksLists.error.fire( ! isSuccess , _callbackContext , xhr, statusText, error);
|
if ( _s.global ) {
|
||||||
if ( !isSuccess && _s.global ) {
|
_globalEventContext.trigger( "ajax" + ( isSuccess ? "Success" : "Error" ) , [ xhr , _s , isSuccess ? success : error ] );
|
||||||
_globalEventContext.trigger( "ajaxError", [xhr, _s, error] );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Complete
|
// Complete
|
||||||
_callbacksLists.complete.fire( 1 , _callbackContext, xhr, statusText);
|
_completeDeferred.fire( _callbackContext, [ xhr , statusText ] );
|
||||||
|
|
||||||
if ( _s.global ) {
|
if ( _s.global ) {
|
||||||
_globalEventContext.trigger( "ajaxComplete", [xhr, _s] );
|
_globalEventContext.trigger( "ajaxComplete", [xhr, _s] );
|
||||||
// Handle the global AJAX counter
|
// Handle the global AJAX counter
|
||||||
|
@ -419,7 +424,8 @@ jQuery.xhr = function( _native ) {
|
||||||
// Callback stuff
|
// Callback stuff
|
||||||
callbackContext,
|
callbackContext,
|
||||||
globalEventContext,
|
globalEventContext,
|
||||||
callbacksLists,
|
deferred,
|
||||||
|
completeDeferred,
|
||||||
// Headers (they are sent all at once)
|
// Headers (they are sent all at once)
|
||||||
requestHeaders,
|
requestHeaders,
|
||||||
// Response headers
|
// Response headers
|
||||||
|
@ -596,135 +602,10 @@ jQuery.xhr = function( _native ) {
|
||||||
// Init data (so that we can bind callbacks early
|
// Init data (so that we can bind callbacks early
|
||||||
reset(1);
|
reset(1);
|
||||||
|
|
||||||
// Install callbacks related methods
|
|
||||||
jQuery.each(callbacksLists, function(name) {
|
|
||||||
var list;
|
|
||||||
xhr[name] = function() {
|
|
||||||
list = callbacksLists[name];
|
|
||||||
if ( list ) {
|
|
||||||
list.bind.apply(list, arguments );
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
// Return the xhr emulation
|
// Return the xhr emulation
|
||||||
return xhr;
|
return xhr;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Create a callback list
|
|
||||||
function createCBList() {
|
|
||||||
|
|
||||||
var functors = [],
|
|
||||||
autoFire = 0,
|
|
||||||
fireArgs,
|
|
||||||
list = {
|
|
||||||
|
|
||||||
fire: function( flag , context ) {
|
|
||||||
|
|
||||||
// Save info for later bindings
|
|
||||||
fireArgs = arguments;
|
|
||||||
|
|
||||||
// Remove autoFire to keep bindings in order
|
|
||||||
autoFire = 0;
|
|
||||||
|
|
||||||
var args = sliceFunc.call( fireArgs , 2 );
|
|
||||||
|
|
||||||
// Execute callbacks
|
|
||||||
while ( flag && functors.length ) {
|
|
||||||
flag = functors.shift().apply( context , args ) !== false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clean if asked to stop
|
|
||||||
if ( ! flag ) {
|
|
||||||
clean();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set autoFire
|
|
||||||
autoFire = 1;
|
|
||||||
},
|
|
||||||
|
|
||||||
bind: function() {
|
|
||||||
|
|
||||||
var args = arguments,
|
|
||||||
i = 0,
|
|
||||||
length = args.length,
|
|
||||||
func;
|
|
||||||
|
|
||||||
for ( ; i < length ; i++ ) {
|
|
||||||
|
|
||||||
func = args[ i ];
|
|
||||||
|
|
||||||
if ( jQuery.isArray(func) ) {
|
|
||||||
|
|
||||||
list.bind.apply( list , func );
|
|
||||||
|
|
||||||
} else if ( isFunction(func) ) {
|
|
||||||
|
|
||||||
// Add if not already in
|
|
||||||
if ( ! pos( func ) ) {
|
|
||||||
functors.push( func );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( autoFire ) {
|
|
||||||
list.fire.apply( list , fireArgs );
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
unbind: function() {
|
|
||||||
|
|
||||||
var i = 0,
|
|
||||||
args = arguments,
|
|
||||||
length = args.length,
|
|
||||||
func,
|
|
||||||
position;
|
|
||||||
|
|
||||||
if ( length ) {
|
|
||||||
|
|
||||||
for( ; i < length ; i++ ) {
|
|
||||||
func = args[i];
|
|
||||||
if ( jQuery.isArray(func) ) {
|
|
||||||
list.unbind.apply(list,func);
|
|
||||||
} else if ( isFunction(func) ) {
|
|
||||||
position = pos(func);
|
|
||||||
if ( position ) {
|
|
||||||
functors.splice(position-1,1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
functors = [];
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get the index of the functor in the list (1-based)
|
|
||||||
function pos( func ) {
|
|
||||||
for (var i = 0, length = functors.length; i < length && functors[i] !== func; i++) {
|
|
||||||
}
|
|
||||||
return i < length ? ( i + 1 ) : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clean the object
|
|
||||||
function clean() {
|
|
||||||
// Empty callbacks list
|
|
||||||
functors = [];
|
|
||||||
// Inhibit methods
|
|
||||||
for (var i in list) {
|
|
||||||
list[i] = jQuery.noop;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
jQuery.extend(jQuery.xhr, {
|
jQuery.extend(jQuery.xhr, {
|
||||||
|
|
||||||
// Add new prefilter
|
// Add new prefilter
|
||||||
|
|
|
@ -902,3 +902,253 @@ test("jQuery.parseJSON", function(){
|
||||||
ok( true, "Test malformed JSON string." );
|
ok( true, "Test malformed JSON string." );
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("jQuery._deferred()", function() {
|
||||||
|
|
||||||
|
expect( 14 );
|
||||||
|
|
||||||
|
var deferred,
|
||||||
|
object,
|
||||||
|
test;
|
||||||
|
|
||||||
|
deferred = jQuery._deferred();
|
||||||
|
|
||||||
|
test = false;
|
||||||
|
|
||||||
|
deferred.then( function( value ) {
|
||||||
|
equals( value , "value" , "Test pre-resolve callback" );
|
||||||
|
test = true;
|
||||||
|
} );
|
||||||
|
|
||||||
|
deferred.resolve( "value" );
|
||||||
|
|
||||||
|
ok( test , "Test pre-resolve callbacks called right away" );
|
||||||
|
|
||||||
|
test = false;
|
||||||
|
|
||||||
|
deferred.then( function( value ) {
|
||||||
|
equals( value , "value" , "Test post-resolve callback" );
|
||||||
|
test = true;
|
||||||
|
} );
|
||||||
|
|
||||||
|
ok( test , "Test post-resolve callbacks called right away" );
|
||||||
|
|
||||||
|
deferred.cancel();
|
||||||
|
|
||||||
|
test = true;
|
||||||
|
|
||||||
|
deferred.then( function() {
|
||||||
|
ok( false , "Manual cancel was ignored" );
|
||||||
|
test = false;
|
||||||
|
} );
|
||||||
|
|
||||||
|
ok( test , "Test manual cancel" );
|
||||||
|
|
||||||
|
deferred = jQuery._deferred().then( function() {
|
||||||
|
return false;
|
||||||
|
} );
|
||||||
|
|
||||||
|
deferred.resolve();
|
||||||
|
|
||||||
|
test = true;
|
||||||
|
|
||||||
|
deferred.then( function() {
|
||||||
|
test = false;
|
||||||
|
} );
|
||||||
|
|
||||||
|
ok( test , "Test cancel by returning false" );
|
||||||
|
|
||||||
|
try {
|
||||||
|
deferred = jQuery._deferred().resolve().then( function() {
|
||||||
|
throw "Error";
|
||||||
|
} , function() {
|
||||||
|
ok( false , "Test deferred cancel on exception" );
|
||||||
|
} );
|
||||||
|
} catch( e ) {
|
||||||
|
strictEqual( e , "Error" , "Test deferred propagates exceptions");
|
||||||
|
deferred.then();
|
||||||
|
}
|
||||||
|
|
||||||
|
test = "";
|
||||||
|
deferred = jQuery._deferred().then( function() {
|
||||||
|
|
||||||
|
test += "A";
|
||||||
|
|
||||||
|
}, function() {
|
||||||
|
|
||||||
|
test += "B";
|
||||||
|
|
||||||
|
} ).resolve();
|
||||||
|
|
||||||
|
strictEqual( test , "AB" , "Test multiple then parameters" );
|
||||||
|
|
||||||
|
test = "";
|
||||||
|
|
||||||
|
deferred.then( function() {
|
||||||
|
|
||||||
|
deferred.then( function() {
|
||||||
|
|
||||||
|
test += "C";
|
||||||
|
|
||||||
|
} );
|
||||||
|
|
||||||
|
test += "A";
|
||||||
|
|
||||||
|
}, function() {
|
||||||
|
|
||||||
|
test += "B";
|
||||||
|
} );
|
||||||
|
|
||||||
|
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 ) {
|
||||||
|
ok( this === jQuery && arguments.length === 1 && doc === document , "Test fire context & args" );
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("jQuery.deferred()", function() {
|
||||||
|
|
||||||
|
expect( 8 );
|
||||||
|
|
||||||
|
jQuery.deferred( function( defer ) {
|
||||||
|
strictEqual( this , defer , "Defer passed as this & first argument" );
|
||||||
|
this.resolve( "done" );
|
||||||
|
}).then( function( value ) {
|
||||||
|
strictEqual( value , "done" , "Passed function executed" );
|
||||||
|
});
|
||||||
|
|
||||||
|
jQuery.deferred().resolve().then( function() {
|
||||||
|
ok( true , "Success on resolve" );
|
||||||
|
}).fail( function() {
|
||||||
|
ok( false , "Error on resolve" );
|
||||||
|
});
|
||||||
|
|
||||||
|
jQuery.deferred().reject().then( function() {
|
||||||
|
ok( false , "Success on reject" );
|
||||||
|
}).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() {
|
||||||
|
|
||||||
|
expect( 11 );
|
||||||
|
|
||||||
|
var object1 = { then: function() { return this; } },
|
||||||
|
object2 = { then: function() { return this; } };
|
||||||
|
|
||||||
|
object2.then._ = [];
|
||||||
|
|
||||||
|
// The use case that we want to match
|
||||||
|
ok(jQuery.isDeferred(jQuery._deferred()), "Simple deferred");
|
||||||
|
ok(jQuery.isDeferred(jQuery.deferred()), "Failable deferred");
|
||||||
|
|
||||||
|
// Some other objects
|
||||||
|
ok(!jQuery.isDeferred(object1), "Object with then & no marker");
|
||||||
|
ok(!jQuery.isDeferred(object2), "Object with then & marker");
|
||||||
|
|
||||||
|
// Not objects shouldn't be matched
|
||||||
|
ok(!jQuery.isDeferred(""), "string");
|
||||||
|
ok(!jQuery.isDeferred(0) && !jQuery.isDeferred(1), "number");
|
||||||
|
ok(!jQuery.isDeferred(true) && !jQuery.isDeferred(false), "boolean");
|
||||||
|
ok(!jQuery.isDeferred(null), "null");
|
||||||
|
ok(!jQuery.isDeferred(undefined), "undefined");
|
||||||
|
|
||||||
|
object1 = {custom: jQuery._deferred().then};
|
||||||
|
|
||||||
|
ok(!jQuery.isDeferred(object1) , "custom method name not found automagically");
|
||||||
|
ok(jQuery.isDeferred(object1,"custom") , "custom method name");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("jQuery.when()", function() {
|
||||||
|
|
||||||
|
expect( 5 );
|
||||||
|
|
||||||
|
var cache, i, deferred = { done: jQuery.deferred().resolve( 1 ).then };
|
||||||
|
|
||||||
|
for( i = 1 ; i < 3 ; i++ ) {
|
||||||
|
jQuery.when( cache || jQuery.deferred( function() {
|
||||||
|
this.resolve( i );
|
||||||
|
}) ).then( function( value ) {
|
||||||
|
strictEqual( value , 1 , "Function executed" + ( i > 1 ? " only once" : "" ) );
|
||||||
|
cache = value;
|
||||||
|
}).fail( function() {
|
||||||
|
ok( false , "Fail called" );
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
cache = 0;
|
||||||
|
|
||||||
|
for( i = 1 ; i < 3 ; i++ ) {
|
||||||
|
jQuery.when( cache || deferred , "done" ).done( function( value ) {
|
||||||
|
strictEqual( value , 1 , "Custom method: resolved" + ( i > 1 ? " only once" : "" ) );
|
||||||
|
cache = value;
|
||||||
|
}).fail( function() {
|
||||||
|
ok( false , "Custom method: fail called" );
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
stop();
|
||||||
|
|
||||||
|
jQuery.when( jQuery( document ) , "ready" ).then( function( test ) {
|
||||||
|
strictEqual( test , jQuery , "jQuery.fn.ready recognized as a deferred" );
|
||||||
|
start();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
Loading…
Reference in a new issue