Simplified the way a Promise is tested for (removed promiseMarker). Removed isCancelled helper method from _Deferred, wasn't used nor tested. Reworked jQuery.Deferred and removed unnecessary variables. Also ensured a Promise will return itself when asked for a Promise. Finally, the jQuery.when tests have been revamped.

This commit is contained in:
jaubourg 2010-12-30 17:06:53 +01:00
parent 64902e0345
commit 7b1e873cd9
2 changed files with 30 additions and 44 deletions

View file

@ -75,10 +75,7 @@ var jQuery = function( selector, context ) {
indexOf = Array.prototype.indexOf, indexOf = Array.prototype.indexOf,
// [[Class]] -> type pairs // [[Class]] -> type pairs
class2type = {}, class2type = {};
// Marker for deferred
promiseMarker = [];
jQuery.fn = jQuery.prototype = { jQuery.fn = jQuery.prototype = {
init: function( selector, context ) { init: function( selector, context ) {
@ -874,7 +871,7 @@ jQuery.extend({
// resolve with this as context and given arguments // resolve with this as context and given arguments
resolve: function() { resolve: function() {
deferred.fire( this , arguments ); deferred.fire( jQuery.isFunction( this.promise ) ? this.promise() : this , arguments );
return this; return this;
}, },
@ -888,11 +885,6 @@ jQuery.extend({
cancelled = 1; cancelled = 1;
callbacks = []; callbacks = [];
return this; return this;
},
// Has this deferred been cancelled?
isCancelled: function() {
return !!cancelled;
} }
}; };
@ -903,38 +895,36 @@ jQuery.extend({
// Typical success/error system // Typical success/error system
Deferred: function( func ) { Deferred: function( func ) {
var errorDeferred = jQuery._Deferred(), var deferred = jQuery._Deferred(),
deferred = jQuery._Deferred(), failDeferred = jQuery._Deferred();
successCancel = deferred.cancel;
// Add errorDeferred methods and redefine cancel // Add errorDeferred methods and redefine cancel
jQuery.extend( deferred , { jQuery.extend( deferred , {
fail: errorDeferred.then, fail: failDeferred.then,
fireReject: errorDeferred.fire, fireReject: failDeferred.fire,
reject: errorDeferred.resolve, reject: failDeferred.resolve,
isRejected: errorDeferred.isResolved, isRejected: failDeferred.isResolved,
// Get a promise for this deferred // Get a promise for this deferred
// 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 ) {
obj = obj || {}; obj = obj || {};
for ( var i in { then:1 , fail:1 , isResolved:1 , isRejected:1 , promise:1 } ) { jQuery.each( "then fail isResolved isRejected".split( " " ) , function( _ , method ) {
obj[ i ] = deferred[ i ]; obj[ method ] = deferred[ method ];
} });
obj.promise = function() {
return obj;
};
return obj; return obj;
} }
} ); } );
// Remove cancel related
delete deferred.cancel;
delete deferred.isCancelled;
// Add promise marker
deferred.promise._ = promiseMarker;
// Make sure only one callback list will be used // Make sure only one callback list will be used
deferred.then( errorDeferred.cancel ).fail( successCancel ); deferred.then( failDeferred.cancel ).fail( deferred.cancel );
// Unexpose cancel
delete deferred.cancel;
// Call given func if any // Call given func if any
if ( func ) { if ( func ) {
@ -946,7 +936,7 @@ jQuery.extend({
// Deferred helper // Deferred helper
when: function( object ) { when: function( object ) {
object = object && object.promise && object.promise._ === promiseMarker ? object = object && jQuery.isFunction( object.promise ) ?
object : object :
jQuery.Deferred().resolve( object ); jQuery.Deferred().resolve( object );
return object.promise(); return object.promise();

View file

@ -1024,30 +1024,26 @@ test("jQuery.Deferred()", function() {
test("jQuery.when()", function() { test("jQuery.when()", function() {
expect( 14 ); expect( 21 );
var fakeDeferred = { then: function() { return this; } };
fakeDeferred.then._ = [];
// Some other objects // Some other objects
jQuery.each( { jQuery.each( {
"Object with then & no marker": { then: jQuery.noop }, "an empty string": "",
"Object with then & marker": fakeDeferred, "a non-empty string": "some string",
"string 1/2": "", "zero": 0,
"string 2/2": "some string", "a number other than zero": 1,
"number 1/2": 0, "true": true,
"number 2/2": 1, "false": false,
"boolean 1/2": true,
"boolean 2/2": false,
"null": null, "null": null,
"undefined": undefined, "undefined": undefined,
"custom method name not found automagically": {custom: jQuery._Deferred().then} "a plain object": {}
} , function( message , value ) { } , function( message , value ) {
notStrictEqual( jQuery.when( value ) , value , message ); ok( jQuery.isFunction( jQuery.when( value ).then( function( resolveValue ) {
strictEqual( resolveValue , value , "Test the promise was resolved with " + message );
} ).promise ) , "Test " + message + " triggers the creation of a new Promise" );
} ); } );