jQuery-1.9.1源码分析系列(六) 延时对象续——辅助函数jQuery.when
$.when的说明
描述: 提供一种方法来执行一个或多个对象的回调函数,返回这些对象的延时(Deferred)对象。
说明(结合实例和源码):
如果你不传递任何参数, jQuery.when()将返回一个resolved(解决)状态的promise对象。
如果向jQuery.when()传入一个参数 , 并且它不是一个Deferred或Promise对象, 那么它会被当作是一个被解决(resolved)的延迟对象,并且绑定到上面的任何 doneCallbacks 都会被立刻执行。向 doneCallbacks 中传入的是原始的参数。在这种情况下,设定的任何 failCallbacks 永远都不会被执行,因为延迟对象永远不会被拒绝(rejected)。例如:
$.when( { testing: 123 } ).done(
function(x) { alert(x.testing); } /* alerts "123" */
);
上面两种情况,源码
//如果没有传递参数或唯一一个参数且不是一个延时对象,直接解决主延时对象即可
if ( !remaining ) {
deferred.resolveWith( resolveContexts, resolveValues );
}
如果向 jQuery.when() 传入一个单独的延迟对象,那么会返回它的 Promise 对象(延迟方法的一个子集)。可以继续绑定 Promise 对象的其它方法,例如, defered.then 。当延迟对象已经被解决(resolved)或被拒绝(rejected)(通常是由创建延迟对象的最初代码执行的),那么就会调用适当的回调函数。例如,由 jQuery.ajax() 返回的 jqXHR 对象是一并立的延迟对象并且可以像下面这样使用:
$.when( $.ajax("test.aspx") ).then(function(data, textStatus, jqXHR){
alert( jqXHR.status ); // alerts 200
});
源码
return deferred.promise();
在多个延迟对象传递给jQuery.when() 的情况下,该方法根据一个新的“宿主” Deferred(延迟)对象,跟踪所有已通过Deferreds聚集状态,返回一个Promise对象。当所有的延迟对象被解决(resolve)时,“宿主” Deferred(延迟)对象才会解决(resolved)该方法,源码
//否则成员延时(Deferred)对象解决的时候才进入该分支判断
//需要等待解决的延时(Deferred)对象数量减一,
//判断还有没有需要等待解决的延时(Deferred)对象,如果有,则判断失败返回
//如果没有则进入分支子代码,执行主延时(Deferred)对象解决deferred.resolveWith(...)
else if ( !( --remaining ) ) {
//最终执行到此步的时候values已经变成所有成员延时(Deferred)对象resolve的参数序列
deferred.resolveWith( contexts, values );
}
或者当其中有一个延迟对象被拒绝(rejected)时,“宿主” Deferred(延迟)对象就会reject(拒绝)该方法,源码
resolveValues[ i ].promise()
.done( updateFunc( i, resolveContexts, resolveValues ) )
//如果有一个成员延时(Deferred)对象拒绝时,则整个主延时(Deferred)对象直接拒绝
.fail( deferred.reject )
.progress( updateFunc( i, progressContexts, progressValues ) );
如果“宿主” Deferred(延迟)对象是(resolved)解决状态时, “宿主” Deferred(延迟)对象的 doneCallbacks (解决回调)将被执行。参数传递给 doneCallbacks提供这解决(resolved)值给每个对应的Deferreds对象,并匹配Deferreds传递给 jQuery.when()的顺序。 例如:
var d1 = $.Deferred();
var d2 = $.Deferred(); $.when( d1, d2 ).done(function ( v1, v2 ) {
console.log( v1 ); // "Fish"
console.log( v2 ); // "Pizza"
}); d1.resolve( "Fish" );
d2.resolve( "Pizza" );
在多延迟情况下,如果Deferreds延迟对象一被拒绝(rejected),jQuery.when()触发立即调用 “宿主” Deferred(延迟)对象的 failCallbacks。请注意在这个时间点上,有一些延迟对象仍然可以是未解决(unresolved)的。 传递给failCallbacks的参数匹配Deferred(延迟)对象的 failCallbacks被 rejected 拒绝的顺序。那么,在这种情况下,如果需要执行一些额外的处理,例如,取消所有未完成的 ajax 请求,你可以在闭包中进行保持 jqXHR 对象的引用,并且在 failCallback 中检查或取消它们。
附上完整的源码
// Deferred helper
when: function( subordinate /* , ..., subordinateN */ ) {
var i = 0,
resolveValues = core_slice.call( arguments ),
length = resolveValues.length, //参数个数 //统计没有被解决的成员,
//如果参数个数不为1,则remaining为参数个数,
//如果参数个数为1且参数是 Deferred(延迟)对象则remaining为参数个数1;否则为0
remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0, //初始化主延时对象,如果参数本身是一个延时对象则用参数即可,否则新建.
deferred = remaining === 1 ? subordinate : jQuery.Deferred(), // Update函数处理resolve和progress的值
updateFunc = function( i, contexts, values ) {
return function( value ) {
contexts[ i ] = this;
values[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value;
//成员延时(Deferred)对象生成进度通知的时候主延时(Deferred)对象调用进行中的回调
//后面代码.progress( updateFunc( i, progressContexts, progressValues),往进度回调列表添加函数的时候第三个参数就是progressValues if( values === progressValues ) {
//调用进行中的回调(progressCallbacks )
deferred.notifyWith( contexts, values ); //否则成员延时(Deferred)对象解决的时候才进入该分支判断
//需要等待解决的延时(Deferred)对象数量减一,
//判断还有没有需要等待解决的延时(Deferred)对象,如果有,则判断失败返回
//如果没有则进入分支子代码,执行主延时(Deferred)对象解决deferred.resolveWith(...)
} else if ( !( --remaining ) ) {
//最终执行到此步的时候values已经变成所有成员延时(Deferred)对象resolve的参数序列
deferred.resolveWith( contexts, values );
}
};
}, progressValues, progressContexts, resolveContexts; //对于没有参数或是有唯一一个非延时对象的,直接认为resolved,也就是后面if ( !remaining ) 分支的处理
//对于参数就是一个延时对象的直接将这个延时对象的deferred.promise()返回即可
//对于参数多于一个的才进入该分支,添加监听器监听成员被解决
if ( length > 1 ) {
progressValues = new Array( length );
progressContexts = new Array( length );
resolveContexts = new Array( length );
for ( ; i < length; i++ ) {
//遍历参数成员,只有成员是延时(Deferred)对象的才需要监听器
if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
resolveValues[ i ].promise()
.done( updateFunc( i, resolveContexts, resolveValues ) )
//如果有一个成员延时(Deferred)对象拒绝时,则整个主延时(Deferred)对象直接拒绝
.fail( deferred.reject )
.progress( updateFunc( i, progressContexts, progressValues ) ); //非延时(Deferred)对象的直接认为已解决,需要等待解决的延时(Deferred)对象数量减一
} else {
--remaining;
}
}
} //如果没有传递参数或唯一一个参数且不是一个延时对象,直接解决主延时对象即可
if ( !remaining ) {
deferred.resolveWith( resolveContexts, resolveValues );
} return deferred.promise();
}
如果觉得本文不错,请点击右下方【推荐】!
jQuery-1.9.1源码分析系列(六) 延时对象续——辅助函数jQuery.when的更多相关文章
- jQuery-1.9.1源码分析系列(十四) 一些jQuery工具
为了给下一章分析动画处理做准备,先来看一下一些工具.其中队列工具在动画处理中被经常使用. jQuery.fn. queue(([ queueName ] [, newQueue ]) || ([ qu ...
- jQuery源码分析系列
声明:本文为原创文章,如需转载,请注明来源并保留原文链接Aaron,谢谢! 版本截止到2013.8.24 jQuery官方发布最新的的2.0.3为准 附上每一章的源码注释分析 :https://git ...
- [转]jQuery源码分析系列
文章转自:jQuery源码分析系列-Aaron 版本截止到2013.8.24 jQuery官方发布最新的的2.0.3为准 附上每一章的源码注释分析 :https://github.com/JsAaro ...
- jQuery源码分析系列(转载来源Aaron.)
声明:非本文原创文章,转载来源原文链接Aaron. 版本截止到2013.8.24 jQuery官方发布最新的的2.0.3为准 附上每一章的源码注释分析 :https://github.com/JsAa ...
- jQuery源码分析系列——来自Aaron
jQuery源码分析系列——来自Aaron 转载地址:http://www.cnblogs.com/aaronjs/p/3279314.html 版本截止到2013.8.24 jQuery官方发布最新 ...
- jquery2源码分析系列
学习jquery的源码对于提高前端的能力很有帮助,下面的系列是我在网上看到的对jquery2的源码的分析.等有时间了好好研究下.我们知道jquery2开始就不支持IE6-8了,从jquery2的源码中 ...
- jQuery-1.9.1源码分析系列完毕目录整理
jQuery 1.9.1源码分析已经完毕.目录如下 jQuery-1.9.1源码分析系列(一)整体架构 jQuery-1.9.1源码分析系列(一)整体架构续 jQuery-1.9.1源码分析系列(二) ...
- MyCat源码分析系列之——结果合并
更多MyCat源码分析,请戳MyCat源码分析系列 结果合并 在SQL下发流程和前后端验证流程中介绍过,通过用户验证的后端连接绑定的NIOHandler是MySQLConnectionHandler实 ...
- MyCat源码分析系列之——SQL下发
更多MyCat源码分析,请戳MyCat源码分析系列 SQL下发 SQL下发指的是MyCat将解析并改造完成的SQL语句依次发送至相应的MySQL节点(datanode)的过程,该执行过程由NonBlo ...
随机推荐
- 数据库中的two phase locking
数据库中的two phase locking 两段锁协议是指每个事务的执行可以分为两个阶段:生长阶段(加锁阶段)和衰退阶段(解锁阶段). 加锁阶段:在该阶段可以进行加锁操作.在对任何数据进行读操作之前 ...
- Android应用安全开发之浅谈加密算法的坑
<Android应用安全开发之浅谈加密算法的坑> 作者:阿里移动安全@伊樵,@舟海 阿里聚安全,一站式解决应用开发安全问题 Android开发中,难免会遇到需要加解密一些数据内 ...
- .NET中那些所谓的新语法之一:自动属性、隐式类型、命名参数与自动初始化器
开篇:在日常的.NET开发学习中,我们往往会接触到一些较新的语法,它们相对以前的老语法相比,做了很多的改进,简化了很多繁杂的代码格式,也大大减少了我们这些菜鸟码农的代码量.但是,在开心欢乐之余,我们也 ...
- .NET中那些所谓的新语法之二:匿名类、匿名方法与扩展方法
开篇:在上一篇中,我们了解了自动属性.隐式类型.自动初始化器等所谓的新语法,这一篇我们继续征程,看看匿名类.匿名方法以及常用的扩展方法.虽然,都是很常见的东西,但是未必我们都明白其中蕴含的奥妙.所以, ...
- MySQL mysqldump数据导出详解
介绍 在日常维护工作当中经常会需要对数据进行导出操作,而mysqldump是导出数据过程中使用非常频繁的一个工具:它自带的功能参数非常多,文章中会列举出一些常用的操作,在文章末尾会将所有的参数详细说明 ...
- 轻量级Java EE企业应用实战(第4版):Struts 2+Spring 4+Hibernate整合开发(含CD光盘1张)
轻量级Java EE企业应用实战(第4版):Struts 2+Spring 4+Hibernate整合开发(含CD光盘1张)(国家级奖项获奖作品升级版,四版累计印刷27次发行量超10万册的轻量级Jav ...
- GitFlow
git工作流 始终保持有master分支(只要有目录,git就自动创建)和develop分支(手动创建) 一.主分支Master二.开发分支Develop三.临时性分支(最后发布要删除的)* 功能(f ...
- jsp 分页, 判断是第一页,和最后一页.
<% //页的行数 int pagesize =20; //当前页 int currentPage = 1; try { currentPage = Integer.parseInt(reque ...
- 【转】WPF防止界面卡死并显示加载中效果
原文地址:http://www.cnblogs.com/linyijia/archive/2013/02/06/2900609.html <Window x:Class="Loadin ...
- 动态给div中新增html
小颖最近接触的项目中用到了 innerHTML 所以小颖今天就自己做了个demo,当当当当代码请看下方: 页面效果: