Skip to content
Permalink
Browse files

Implements joined jQuery.when statements. Makes it so calling jQuery.…

…when with no parameter returns a resolved promise. Ensures promise method on promises supports the promise(obj) signature. Ensures a deferred and its promise always return the same promise (itself for the promise). Unit tests provided.
  • Loading branch information
jaubourg committed Jan 16, 2011
1 parent cfca6d3 commit c272f5f7da3473fd5ac85efe783a0d63608ec62b
Showing with 79 additions and 14 deletions.
  1. +36 −11 src/core.js
  2. +43 −3 test/unit/core.js
@@ -898,9 +898,10 @@ jQuery.extend({
Deferred: function( func ) {

var deferred = jQuery._Deferred(),
failDeferred = jQuery._Deferred();
failDeferred = jQuery._Deferred(),
promise;

// Add errorDeferred methods and redefine cancel
// Add errorDeferred methods, then and promise
jQuery.extend( deferred , {

then: function( doneCallbacks , failCallbacks ) {
@@ -914,13 +915,15 @@ jQuery.extend({
// Get a promise for this deferred
// If obj is provided, the promise aspect is added to the object
promise: function( obj ) {
obj = obj || {};
jQuery.each( "then done fail isResolved isRejected".split( " " ) , function( _ , method ) {
if ( obj == null ) {
if ( promise ) {
return promise;
}
promise = obj = {};
}
jQuery.each( "then done fail isResolved isRejected promise".split( " " ) , function( _ , method ) {

This comment has been minimized.

Copy link
@scottgonzalez

scottgonzalez Jan 16, 2011

Member

Splitting the string of method names into an array should happen outside of the promise method so that we don't incur the overhead on every call.

This comment has been minimized.

Copy link
@jaubourg

jaubourg Jan 16, 2011

Author Member

Yeah, I was thinking about this actually.

This comment has been minimized.

Copy link
@jaubourg
obj[ method ] = deferred[ method ];
});
obj.promise = function() {
return obj;
};
return obj;
}

@@ -942,10 +945,32 @@ jQuery.extend({

// Deferred helper
when: function( object ) {
object = object && jQuery.isFunction( object.promise ) ?
object :
jQuery.Deferred().resolve( object );
return object.promise();
var args = arguments,
length = args.length,
deferred = length <= 1 && object && jQuery.isFunction( object.promise ) ?
object :
jQuery.Deferred(),
promise = deferred.promise(),
resolveArray;

if ( length > 1 ) {
resolveArray = new Array( length );
jQuery.each( args, function( index, element, args ) {
jQuery.when( element ).done( function( value ) {
args = arguments;
resolveArray[ index ] = args.length > 1 ? slice.call( args , 0 ) : value;
if( ! --length ) {
deferred.fire( promise, resolveArray );
}
}).fail( function() {
deferred.fireReject( promise, arguments );
});
return !deferred.isRejected();
});
} else if ( deferred !== object ) {
deferred.resolve( object );
}
return promise;
},

// Use of jQuery.browser is frowned upon.
@@ -21,7 +21,7 @@ test("jQuery()", function() {
equals( jQuery(null).length, 0, "jQuery(null) === jQuery([])" );
equals( jQuery("").length, 0, "jQuery('') === jQuery([])" );

var obj = jQuery("div")
var obj = jQuery("div");
equals( jQuery(obj).selector, "div", "jQuery(jQueryObj) == jQueryObj" );

// can actually yield more than one, when iframes are included, the window is an array as well
@@ -1003,7 +1003,7 @@ test("jQuery._Deferred()", function() {

test("jQuery.Deferred()", function() {

expect( 4 );
expect( 6 );

jQuery.Deferred( function( defer ) {
strictEqual( this , defer , "Defer passed as this & first argument" );
@@ -1023,11 +1023,16 @@ test("jQuery.Deferred()", function() {
}, function() {
ok( true , "Error on reject" );
});

var tmp = jQuery.Deferred();

strictEqual( tmp.promise() , tmp.promise() , "Test deferred always return same promise" );
strictEqual( tmp.promise() , tmp.promise().promise() , "Test deferred's promise always return same promise as deferred" );
});

test("jQuery.when()", function() {

expect( 21 );
expect( 23 );

// Some other objects
jQuery.each( {
@@ -1050,6 +1055,10 @@ test("jQuery.when()", function() {

} );

ok( jQuery.isFunction( jQuery.when().then( function( resolveValue ) {
strictEqual( resolveValue , undefined , "Test the promise was resolved with no parameter" );
} ).promise ) , "Test calling when with no parameter triggers the creation of a new Promise" );

var cache, i;

for( i = 1 ; i < 4 ; i++ ) {
@@ -1064,6 +1073,37 @@ test("jQuery.when()", function() {
}
});

test("jQuery.when() - joined", function() {

expect(8);

jQuery.when( 1, 2, 3 ).done( function( a, b, c ) {
strictEqual( a , 1 , "Test first param is first resolved value - non-observables" );
strictEqual( b , 2 , "Test second param is second resolved value - non-observables" );
strictEqual( c , 3 , "Test third param is third resolved value - non-observables" );
}).fail( function() {
ok( false , "Test the created deferred was resolved - non-observables");
});

var successDeferred = jQuery.Deferred().resolve( 1 , 2 , 3 ),
errorDeferred = jQuery.Deferred().reject( "error" , "errorParam" );

jQuery.when( 1 , successDeferred , 3 ).done( function( a, b, c ) {
strictEqual( a , 1 , "Test first param is first resolved value - resolved observable" );
same( b , [ 1 , 2 , 3 ] , "Test second param is second resolved value - resolved observable" );
strictEqual( c , 3 , "Test third param is third resolved value - resolved observable" );
}).fail( function() {
ok( false , "Test the created deferred was resolved - resolved observable");
});

jQuery.when( 1 , errorDeferred , 3 ).done( function() {
ok( false , "Test the created deferred was rejected - rejected observable");
}).fail( function( error , errorParam ) {
strictEqual( error , "error" , "Test first param is first rejected value - rejected observable" );
strictEqual( errorParam , "errorParam" , "Test second param is second rejected value - rejected observable" );
});
});

test("jQuery.subclass", function(){
expect(378);

0 comments on commit c272f5f

Please sign in to comment.
You can’t perform that action at this time.