jQuery中延迟对象then方法和when方法源码分析

来源:互联网 发布:软件测试的周期 编辑:程序博客网 时间:2024/05/20 21:42

then方法先根据父级状态执行添加的函数,然后再根据情况修改状态。

then: function( /* fnDone, fnFail, fnProgress */ ) {var fns = arguments;return jQuery.Deferred(function( newDefer ) {jQuery.each( tuples, function( i, tuple ) {var action = tuple[ 0 ],fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];// deferred[ done | fail | progress ] for forwarding actions to newDefer//then方法添加的函数的执行依赖于父级延迟对象的状态,子级对象的状态,根据不同情况进行判断deferred[ tuple[1] ](function() {var returned = fn && fn.apply( this, arguments );//如果then方法添加的函数有返回值并且是延迟对象,则该延迟对象决定子级延迟对象的状态if ( returned && jQuery.isFunction( returned.promise ) ) {returned.promise().done( newDefer.resolve ).fail( newDefer.reject ).progress( newDefer.notify );} else {//then方法添加的函数没有返回值,或返回值不是延迟对象,子级状态跟父级保持一致//  then方法添加的函数有返回值,不是延迟对象,返回值作为下一个then方法添加函数的参数newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );}});});fns = null;}).promise();

难点在于理解第九行代码中的deferred指的是父级中的deferred对象,上述代码相当于:

 function aa ( newDefer ) {jQuery.each( tuples, function( i, tuple ) {var action = tuple[ 0 ],fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];// deferred[ done | fail | progress ] for forwarding actions to newDeferdeferred[ tuple[1] ](function() {var returned = fn && fn.apply( this, arguments );if ( returned && jQuery.isFunction( returned.promise ) ) {returned.promise().done( newDefer.resolve ).fail( newDefer.reject ).progress( newDefer.notify );} else {newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );}});});fns = null;} then: function( /* fnDone, fnFail, fnProgress */ ) {var fns = arguments;return jQuery.Deferred(aa).promise();},
aa函数中的deferred无法访问子级中的deferred对象

if ( func ) {      func.call( deferred, deferred );  }

 var aaa = function(){            var f = $.Deferred();            f.reject();            f.fail(function(){            alert('222');            })//          return f;           };           var bbb = function(){            var e = $.Deferred();            e.reject();            e.fail(function(){            alert('333');            })            return e;           };            var d = $.Deferred();            d.resolve();            d.done(function(){            alert('111')            });            var t = d.then(aaa,bbb);            t.then(function(){            alert('555');            },function(){            alert('666');            });
结果是依次弹出111,222,555;如果aaa函数返回一个延迟对象,并且状态是reject,则依次弹出111,222,666

var val=1            var d = $.Deferred();            d.resolve(val);            d.done(function(val){            alert(val);//1            }).then(function(val){            return 2*val            }).then(function(val){            alert(val);//2            });

 var val=1            var d = $.Deferred();            d.resolve(val);            d.done(function(val){            alert(val);//1            }).then(function(val){            alert(val);//1            }).then(function(val){            alert(val);//undefined            });

第一个then方法添加的函数的参数和父级的相同:

deferred[ tuple[1] ](function() {         var returned = fn && fn.apply( this, arguments );             ...}
从第二个then开始,添加函数的参数由上个then方法添加的函数的返回值决定,如果返回一个延迟对象,则参数由返回延迟对象的参数决定:

            var val=1            var d = $.Deferred();            d.resolve(val);            d.then(function(val){            var call = $.Deferred();            call.resolve('a');            call.done(function(val){            alert(val);//a            })            return call;            }).then(function(val){            alert(val);//a            });
原因是:返回的延迟对象,通过“add”,添加了子级延迟对象的状态函数,参数也会相应传递
if ( returned && jQuery.isFunction( returned.promise ) ) {returned.promise().done( newDefer.resolve ).fail( newDefer.reject ).progress( newDefer.notify );}
从第二个then开始,添加函数的参数由上个then方法添加的函数的返回值决定,如果返回的不是延迟对象,则返回值直接作为参数。
            var val=1            var d = $.Deferred();            d.resolve(val);            d.then(function(val){            alert(val);//1            return 100;            }).then(function(val){            alert(val);//100            });
原因:
newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );

怎么理解$.when(),$.when()返回的是promise对象,即无法修改状态,只能添加回调函数,
  因为状态是由参数中的延迟对象的状态共同决定的,
  1.当没有参数时,remaining=0,创建延迟对象,直接调用deferred.resolveWith
  2.只有一个参数时,并且不是延迟对象,创建延迟对象,直接调用deferred.resolveWith
  3.只有一个参数,并且是延迟对象,返回该延迟对象的deferred.promise()
  4.多个延迟对象并存,只要有一个reject,返回新对象的状态为reject
  5.多个延迟对象并存,没有一个reject,只要有一个process,返回对象的状态为notify
  6.存在的延迟对象都是resolve时,调用deferred.resolveWith

when: function( subordinate /* , ..., subordinateN */ ) {var i = 0,resolveValues = core_slice.call( arguments ),length = resolveValues.length,// the count of uncompleted subordinatesremaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,// the master Deferred. If resolveValues consist of only a single Deferred, just use that.deferred = remaining === 1 ? subordinate : jQuery.Deferred(),// Update function for both resolve and progress valuesupdateFunc = function( i, contexts, values ) {return function( value ) {contexts[ i ] = this;values[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value;if( values === progressValues ) {deferred.notifyWith( contexts, values );} else if ( !( --remaining ) ) {deferred.resolveWith( contexts, values );}};},progressValues, progressContexts, resolveContexts;// add listeners to Deferred subordinates; treat others as resolvedif ( length > 1 ) {progressValues = new Array( length );progressContexts = new Array( length );resolveContexts = new Array( length );for ( ; i < length; i++ ) {if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {resolveValues[ i ].promise().done( updateFunc( i, resolveContexts, resolveValues ) ).fail( deferred.reject ).progress( updateFunc( i, progressContexts, progressValues ) );} else {--remaining;}}}// if we're not waiting on anything, resolve the masterif ( !remaining ) {deferred.resolveWith( resolveContexts, resolveValues );}return deferred.promise();}