jQuery回调、递延对象总结(下篇) —— 解密jQuery.when方法
前言:
前一篇文章中重点总结了一下then方法,它主要用来处理多个异步任务按顺序执行,即前一个任务处理完了,再继续下一个,以此类推;
而这一章节jQuery.when方法也是处理多个异步任务,它把多个异步任务(Promise对象)合并为一个Promise对象,这个合并后的Promise对象
到底是如何来更新它的状态,即何时执行,拒绝?让我们继续往下看吧!
jQuery回调、递延对象总结篇索引:
jQuery回调、递延对象总结(上篇)—— jQuery.Callbacks
jQuery回调、递延对象总结(中篇) —— 神奇的then方法
jQuery回调、递延对象总结(下篇) —— 解密jQuery.when方法
设计思路(意图)
执行jQuery.when将会返回一个Promise对象,我们称作由when生成的Promise对象,如果给定的所有Promise对象均已执行,就立即执行
由when方法产生的Promise对象,如果给定的Promise对象中有任意一个被拒绝,就立即拒绝由when生成的Promise对象,这样做的意图
好像就是为了解决这样一种需求:在指定的多个异步事件都完成了,然后才能干自己想干的事情
源码解析
jQuery.extend({
// Deferred helper
// 参数为Promise对象,我们称作:给定的Promise对象
// when函数内部的deferred对象,我们称作:由when生成的Promise对象
when: function( subordinate /* , ..., subordinateN */ ) {
var i = 0,
resolveValues = core_slice.call( arguments ),
length = resolveValues.length,
// the count of uncompleted subordinates
// 用来存储给定的未执行(解决)的Promise对象的个数
remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,
// the master Deferred. If resolveValues consist of only a single Deferred, just use that.
// 我们称deferred为when生成的Promise对象
deferred = remaining === 1 ? subordinate : jQuery.Deferred(),
// Update function for both resolve and progress values
updateFunc = function( i, contexts, values ) {
return function( value ) {
contexts[ i ] = this;
values[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value;
// 如果给定的任意一个Promise对象未执行或拒绝,则通知由when生成的Promise对象为pending状态
// 注:contexts是由所有给定的Promise对象组成的数组,
// values是由处理所有给定的Promise对象的回调的参数组成的数组
if( values === progressValues ) {
deferred.notifyWith( contexts, values );
}
// 如果给定的Promise对象已执行(解决),且当未执行的Promise对象个数为0,
// 即:给定的所有Promise对象都已执行(解决),则立即执行由when生成的Promise对象
// 注:contexts是由所有给定的Promise对象组成的数组,
// values是由处理所有给定的Promise对象的回调的参数组成的数组(请看实例1)
else if ( !( --remaining ) ) {
deferred.resolveWith( contexts, values );
}
};
},
progressValues, progressContexts, resolveContexts;
// add listeners to Deferred subordinates; treat others as resolved
if ( length > 1 ) {
progressValues = new Array( length );
progressContexts = new Array( length );
// resolveValues = core_slice.call( arguments ) // 别忘了最上面的这行代码
resolveContexts = new Array( length );
for ( ; i < length; i++ ) {
// 如果给定when的参数是一个Promise对象,则通知由when生成的Promise对象,通知什么,如何通知?
// 如果给定的Promise对象已执行,则执行由when生成的Promise对象(要等到所有给定Promise对象全部执行)
// 如果给定的任意一个Promise对象已拒绝,则拒绝由when生成的Promise对象
// 如果未执行或拒绝,默认是pending状态
if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
resolveValues[ i ].promise()
.done( updateFunc( i, resolveContexts, resolveValues ) )
.fail( deferred.reject )
.progress( updateFunc( i, progressContexts, progressValues ) );
}
// 如果给定的不是一个Promise对象,那么负责减一
else {
--remaining;
}
}
}
// if we're not waiting on anything, resolve the master
// 如果传递给when的参数都不是递延对象,则执行由when生成的Promise对象
if ( !remaining ) {
// resolveContexts为一个空数组new Array( length ),resolveValues是由when参数组成的一个数组
deferred.resolveWith( resolveContexts, resolveValues );
}
return deferred.promise();
}
});
实例:关于执行由when生成的Promise对象的参数的问题
var promiseA = $.Deferred();
var promiseB = $.Deferred(); var doneFn = function(arg){
console.log(arg);
}; promiseA.done(doneFn);
promiseB.done(doneFn); promiseA.resolve('A'); // 'A'
promiseB.resolve('B'); // 'B' var whenFn = function(arg1, arg2){
console.log(this[0] === promiseA.promise()); // true
console.log(this[1] === promiseB.promise()); // true
console.log('promise' + arg1 + ', promise' + arg2 + ' All done!');
};
var whenPromise = jQuery.when(promiseA, promiseB);
whenPromise.done(whenFn); // true true 'promiseA, promiseB All done!'
jQuery回调、递延对象总结:
递延对象中的then方法作用于使多个异步任务按照顺序执行,而jQuery.when方法作用于在多个并发的异步任务执行完毕后再干自己感兴趣的事情;
jQuery递延对象是基于jQuery回调对象架构的,如果你想熟练掌握jQuery递延对象,请先移步jQuery.Callbacks对象
PS: 如有描述错误,请帮忙指正,如果你们有不明白的地方也可以发邮件给我,
jQuery回调、递延对象总结(下篇) —— 解密jQuery.when方法的更多相关文章
- jQuery - 01. jQuery特点、如何使用jQuery、jQuery入口函数、jQuery和DOM对象的区别、jQuery选择器、
this指的是原生js的DOM对象 .css(“”):只写一个值是取值,写俩值是赋值 window.onload === $(document).ready(); $(“”):获取元素 标 ...
- jQuery回调、递延对象总结(中篇) —— 神奇的then方法
前言: 什么叫做递延对象,生成一个递延对象只需调用jQuery.Deferred函数,deferred这个单词译为延期,推迟,即延迟的意思,那么在jQuery中 又是如何表达延迟的呢,从递延对象中的t ...
- jQuery回调、递延对象总结(上篇)—— jQuery.Callbacks
前言: 作为参数传递给另一个函数执行的函数我们称为回调函数,那么该回调又是否是异步的呢,何谓异步,如:作为事件处理器,或作为参数传递给 (setTimeout,setInterval)这样的异步函数, ...
- jQuery回调、递延对象总结
jQuery回调.递延对象总结(上篇)—— jQuery.Callbacks jQuery回调.递延对象总结(中篇) —— 神奇的then方法 jQuery回调.递延对象总结(下篇) —— 解密jQu ...
- jQuery回调、递延对象总结(一)jQuery.Callbacks详解
前言: 作为参数传递给另一个函数执行的函数我们称为回调函数,那么该回调又是否是异步的呢,何谓异步,如:作为事件处理器,或作为参数传递给 (setTimeout,setInterval)这样的异步函数, ...
- jQuery的deferred对象详解 jquery回调函数
http://www.ruanyifeng.com/blog/2011/08/a_detailed_explanation_of_jquery_deferred_object.html jQuery的 ...
- 解密jQuery内核 Sizzle引擎筛选器 - 位置伪类(一)
本章开始分析过滤器,根据API的顺序来 主要涉及的知识点 jQuery的组成 pushStack方法的作用 sizzle伪类选择器 首页我们知道jQuery对象是一个数组对象 内部结构 jQuery的 ...
- 解密jQuery事件核心 - 绑定设计(一)
说起jQuery的事件,不得不提一下Dean Edwards大神 addEvent库,很多流行的类库的基本思想从他那儿借来的 jQuery的事件处理机制吸取了JavaScript专家Dean Edwa ...
- 解密jQuery事件核心 - 委托设计(二)
第一篇 http://www.cnblogs.com/aaronjs/p/3444874.html 从上章就能得出几个信息: 事件信息都存储在数据缓存中 对于没有特殊事件特有监听方法和普通事件都用ad ...
随机推荐
- vs2010 mvc3安装时报错
今天在研究以往的商城项目时,由于前台使用的是MVC3,在没有安装MVC3的插件时,提示未能加载项目,但是在安装过程中,又提示安装失败: 决定折腾一下->居然找到一篇以前别人写的神作,特此记录一下 ...
- HDU4348 To the moon
Time Limit: 2000MS Memory Limit: 65536KB 64bit IO Format: %I64d & %I64u Description Backgrou ...
- iOS GCD中的dispatch_group
假如有一组任务,A,B,C,D,其中ABC是可以并行的,D是必须在ABC任务完成后再执行的. (举个场景,比如吃饭前必须先做菜.做饭和买饮料,然后才能开吃) 1.关于ABC的并行: 采用多线程的方式就 ...
- 帝国cms一些常用的修改路径
1.信息提示改成弹出框提示 修改e/message/index.php 2.修改提示信息 语言包e/data/language/gb/pub/q_message.php 3.文章设置权限后没登录提示模 ...
- POJ 1182 食物链(带权并查集)
传送门 食物链 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 65579 Accepted: 19336 Descri ...
- HDU 1754 I Hate It(线段树模板题)
题目链接: 传送门 I Hate It Time Limit: 3000MS Memory Limit: 32768 K Description 很多学校流行一种比较的习惯.老师们很喜欢询问, ...
- django入门记录 2
1. 创建一个app, python manage.py startapp appname 2. 设计model,在appname/目录下编辑好model 3. 检测model的修改,python ...
- 【Beta版本】冲刺-Day6
队伍:606notconnected 会议时间:12月14日 目录 一.行与思 二.站立式会议图片 三.燃尽图 四.代码Check-in 一.行与思 张斯巍(433) 今日进展:修改界面规范,应用图标 ...
- nginx跨域设置
nginx跨域问题例子:访问http://10.0.0.10/ 需要能实现跨域 操作:http://10.0.0.10/项目是部署在tomcat里面,tomcat跨域暂时还不会,按照网上的方法操作也没 ...
- linux basis --- common commands
switch to root : sudo su switch to users : su god(user name) set root password : sudo passwd root ch ...