jquery中的 deferred之 when (三)
先来看使用案例:
var def1 = $.Deferred();
var def2 = $.Deferred();
var def3 = $.Deferred();
var def4 = $.Deferred(); var fun1 = function (def) {
setTimeout(function () {
console.log("fun1 resolve");
def.resolve();
}, 3000);
return def;
};
var fun2 = function (def) {
setTimeout(function () {
console.log("fun2 resolve");
def.resolve();
}, 2000);
return def;
};
var fun3 = function (def) {
setTimeout(function () {
console.log("fun3 resolve");
def.resolve();
}, 1000);
return def;
};
var fun4 = function (def) {
setTimeout(function () {
console.log("fun4 resolve");
def.resolve();
}, 1000);
return def;
};
$.when(fun1(def1), fun2(def2), fun3(def3),fun4(def4)).done(function () {
console.log("并行执行完毕");
});
//执行结果:
//fun3 resolve
//fun4 resolve
//fun2 resolve
//fun1 resolve
//并行执行完毕
执行的过程如下:

源码分析:
// Deferred helper
when: function( subordinate /* , ..., subordinateN */ ) {
var i = 0,
resolveValues = core_slice.call( arguments ),
length = resolveValues.length, // the count of uncompleted subordinates
remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0, // the master Deferred. If resolveValues consist of only a single Deferred, just use that.
//20170620 huanhua 这就是 when里面的参数 subordinate必须是返回 deferred对象的函数的原因。
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;
//20170624 huanhua 在 progess 中时 ,传递的 values 就是 progressValues ,所以 此时 values === progressValues 是成立的,触发 deferred.notifyWith
if( values === progressValues ) {
deferred.notifyWith(contexts, values);
//20170624 huanhua 在 done 时,传递的 values 就是 resolveValues ,所以 此时 values === progressValues 是不成立的,
//在 remaining = 0,全部都执行完了 ,触发 deferred.resolveWith( contexts, values );
} 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 );
resolveContexts = new Array(length);
for (; i < length; i++) {
//20170624 huanhua 判断传入的个参数是否是 deferred 对象
//如果是
if (resolveValues[i] && jQuery.isFunction(resolveValues[i].promise)) {
//20170625 huanhua 给 when()参数中的各个对象注册方法
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 master
//20170624 huanhua 如果一个都没参数都没传递,就直接执行
if ( !remaining ) {
deferred.resolveWith( resolveContexts, resolveValues );
}
return deferred.promise();
}
$.when(fun1(def1), fun2(def2), fun3(def3),fun4(def4))返回的就是一个 Deferred.promise对象.
updateFunc = function( i, contexts, values ) {
return function (value) {
contexts[ i ] = this;
values[i] = arguments.length > 1 ? core_slice.call(arguments) : value;
//20170624 huanhua 在 progess 中时 ,传递的 values 就是 progressValues ,所以 此时 values === progressValues 是成立的,触发 deferred.notifyWith
if( values === progressValues ) {
deferred.notifyWith(contexts, values);
//20170624 huanhua 在 done 时,传递的 values 就是 resolveValues ,所以 此时 values === progressValues 是不成立的,
//在 remaining = 0,全部都执行完了 ,触发 deferred.resolveWith( contexts, values );
} else if ( !( --remaining ) ) {
deferred.resolveWith( contexts, values );
}
};
},
$.when(fun1(def1), fun2(def2), fun3(def3),fun4(def4))中,fun1(def1)给这个的返回结果def1注册 done(),并且此时给def1.done()注册的方法是在 done中最后执行,有一段核心代码
//在 remaining = 0,全部都执行完了 ,触发 deferred.resolveWith( contexts, values );
} else if ( !( --remaining ) ) {
deferred.resolveWith( contexts, values );
}
remaining闭包when的参数个数,当所有的参数都执行完了的时候,就调用
$.when(fun1(def1), fun2(def2), fun3(def3),fun4(def4))中的对象 deferred.resolveWith().
通过这个思路我们可以简化个案例,得到这个所有人都要度过河的案例:
var Person = function (name) {
var name = name;
var listDo = [];
this.do = function (fn) {
listDo.push(fn);
};
this.fire = function () {
for (var xh in listDo) {
listDo[xh](name);
}
};
};
var Duhe = function (person1, person2, person3, person4) {
var listDo = [];
var length = arguments.length;
var that = this;
var interval = [3000,2000,2500,1000];
for (var arg in arguments) {
arguments[arg].do(function (name) {
setTimeout(function () {
console.log(name + ":渡河成功!");
if (!(--length)) {
that.fire();
}
}, interval[arg]);
});
};
for (var arg in arguments) {
arguments[arg].fire();
};
this.do = function (fn) {
listDo.push(fn);
return this;
};
this.fire = function () {
for(var xh in listDo){
listDo[xh]();
}
};
}
var duhe = new Duhe(new Person("Person1"), new Person("Person2"), new Person("Person3"), new Person("Person4"), new Person("Person5"));
duhe.do(function () { console.log("所有人员都渡河成功!"); });
//答案:
//Person5:渡河成功!
//Person4:渡河成功!
//Person2:渡河成功!
//Person3:渡河成功!
//Person1:渡河成功!
//所有人员都渡河成功!
在我们实际工作中这个思路很重要。
jquery中的 deferred之 when (三)的更多相关文章
- javascript 学习笔记之JQuery中的Deferred对象
Deffered是Jquery中的一个非常重要的对象,从1.5版本之后,Jquery中的ajax操作都基于Deffered进行了重构,这个对象的处理模式就像其他Javascript框中的Promise ...
- jQuery中的Deferred和promise
promise:http://www.alloyteam.com/2014/05/javascript-promise-mode/ 1 jQuery 中的 Deferred 和 Promises : ...
- jQuery中的常用内容总结(三)
jQuery中的常用内容总结(三) 转载请注明地址:http://www.cnblogs.com/funnyzpc/p/7571998.html 内容提要 选择器(第一节) 选择器的扩展方法(第一节) ...
- 深入理解jQuery中的Deferred
引入 1 在开发的过程中,我们经常遇到某些耗时很长的javascript操作,并且伴随着大量的异步. 2 比如我们有一个ajax的操作,这个ajax从发出请求到接收响应需要5秒,在这5秒内我们可以 ...
- 锋利的jQuery ——jQuery中的DOM操作(三)
一.DOM的操作分类 1>DOM Core 2>HTML-DOM 3>CSS-DOM 二.jQuery中的DOM操作 DOM树 ①查找节点 1)查找元素节点 利用jQuery ...
- jQuery 中的 Deferred 和 Promises(转)
转自:http://www.css88.com/archives/4750/comment-page-1 看前首先了解:Promises/A规范,具体可以看这里,http://www.css88.co ...
- jquery中的 deferred之 then (二)
例: var def = $.Deferred(); var prs1 = def.then(function (val) { var result = val + "_123" ...
- jQuery中的deferred对象和extend方法
1⃣️deferred对象 deferred对象是jQuery的回调函数解决方案,它是从jQuery1.5.0版本开始引入的功能 deferred对象的方法 (1) $.Deferred() 生成一个 ...
- jquery中ajax方法返回的三种数据类型:text、json、xml;
1.当dataType:"text"时,处理页面用的是DBDA类中的Strquery()方法,所以返回的数据是下面这样的,所以要对返回来的数据用split根据“|”和“^”来分割, ...
随机推荐
- 关于PCA
PCA是常见的降维技术. 对于使用PCA来进行降维的数据,需要进行预处理,是指能够实现均值为0,以及方差接近.如何来确定到底哪个维度是"主成分"?就要某个axis的方差. 为什么要 ...
- 工控随笔_16_西门子_S7-200.Smart软件安装兼容性说明和错误代码:error code hr=0x80070430
现在西门子的软件是更新换代太快了,前几年还是Step 7 Micro/Win,后来又出了S7-200 Smart PLC,理所当然的编程调试软件也水涨船高,出了新的Step 7 Micro/Win ...
- C# 操作redis
下载 redis windows 版本 官网目前没有windows安装下载,下载地址为 https://github.com/MicrosoftArchive/redis/releases 直接点击安 ...
- PROC IMPORT 选项
GETNAMES=YES;导入源文件字段名作为SAS数据集的字段名MIXED=NO;若某一列中包含数值型和字符型变量,将数值型按照缺省值处理.若选的是YES则是将数值型转换成字符型存储,默认为NOSC ...
- 面试题_默认传参list
# ###2.值是多少 def extendList(val, list=[]): list.append(val) return list 如果默认形参是列表,会提前在内存中开辟一个空间存储列表 如 ...
- Vue公司项目实战步骤
一.无权限,无验证的Vue项目 1.打好HTML+CSS+JS基础,及<Vue 2.0 实战> 2.编写用mock设计的案例: 3.将以上案例的后台用C#改写: 二.带安全验证的Vue项目 ...
- JAVA 中BIO,NIO,AIO的理解 (转)
转自: http://qindongliang.iteye.com/blog/2018539 另外类似可参考资料 :http://www.360doc.com/content/13/1029/20/9 ...
- 使用shell解析脚本依赖关系,并自动补数
将脚本依赖关系放到表中 使用shell解析脚本依赖关系,递归的计算各个脚本. #!/bin/bash # dm 补数 basepath=$(cd ``; pwd) cd $basepath sourc ...
- 一文洞悉Python必备50种算法!资深大牛至少得掌握25种!
一.环境需求 二.怎样使用 三.本地化 3.1扩展卡尔曼滤波本地化 3.2无损卡尔曼滤波本地化 3.3粒子滤波本地化 3.4直方图滤波本地化 四.映射 4.1高斯网格映射 4.2光线投射网格映射 4. ...
- RNN探索(2)之手写数字识别
这篇博文不介绍基础的RNN理论知识,只是初步探索如何使用Tensorflow,之后会用笔推导RNN的公式和理论,现在时间紧迫所以先使用为主~~ import numpy as np import te ...