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();}
阅读全文
0 0
- jQuery中延迟对象then方法和when方法源码分析
- jquery 中的deffered和promise对象方法及$when done then的使用
- jquery deferred对象 then(),when()方法 ,解决回调函数嵌套
- jQuery.when()方法测试笔记及源码分析
- jQuery回调、递延对象,then方法
- case when then 中判断null的方法
- case when then 中判断null的方法
- case when then 中判断null的方法
- case when then 中判断null的方法
- jQuery.extend()方法和jQuery.fn.extend()方法源码分析
- jquery源码分析(2) jQuery对象的一些方法和属性 1
- jquery源码分析(2) jQuery对象的一些方法和属性 2
- jquery源码分析(2) jQuery对象的一些方法和属性 3
- jQuery静态方法parseJSON方法使用和源码分析
- jQuery源码分析之removeAttr方法和attr方法
- jQuery源码分析之buildFragment方法和clone方法
- jquery的when和Deferred方法
- jquery中的工具方法--Deferred和when
- feignclient设置hystrix参数
- 2016 Europe
- 用java编写webservice和在tomcat上部署时遇到的一些问题
- Java I/O 操作及优化建议
- 输出一个整数的每一位
- jQuery中延迟对象then方法和when方法源码分析
- 线程总结
- The C Programming Language 练习题2-8
- es6入门(二):解构赋值和字符串的扩展
- SourceTree<四>子模块
- 35 个 Java 代码性能优化总结
- 初次用construct2编游戏
- 网页动画
- 谈谈谷歌word2vec的原理