Implements joined jQuery.when statements. Makes it so calling jQuery.when with no...
authorjaubourg <j@ubourg.net>
Sun, 16 Jan 2011 16:41:39 +0000 (17:41 +0100)
committerjaubourg <j@ubourg.net>
Sun, 16 Jan 2011 16:41:39 +0000 (17:41 +0100)
src/core.js
test/unit/core.js

index 0bf0cb4..25ef22d 100644 (file)
@@ -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 ) {
                                        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.
index db160b2..8e3756a 100644 (file)
@@ -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);