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根据“|”和“^”来分割, ...
随机推荐
- mvc项目远程发布到windows server服务器
1.安装IIS的时候需要将这两个选项勾选起来 2.确保 管理服务委派 这个选项存在 3.添加委派规则 4.配置IIS管理用户,后续需要用这个用户进行发布连接 5.配置站点的IIS权限 选择刚才在前面设 ...
- jq源码判断数据类型
4.Object.prototype.toString.call() 1 var a = Object.prototype.toString; 2 3 console.log(a.call(" ...
- flutter mac 下安装
- Eclipse Memory Analyzer 分析内存泄露
OutOfMemoryError示例 代码 package com.walson.heap; import java.util.ArrayList;import java.util.List; /** ...
- 执行代码出现ImportError:attempted relative import with no known parent package
前言 在这篇文章中,我将会解析 ImportError: attempted relative import with no known parent package 这个异常的原因.当你在运行的py ...
- 知识点:Mysql 索引原理完全手册(2)
知识点:Mysql 索引原理完全手册(1) 知识点:Mysql 索引原理完全手册(2) 知识点:Mysql 索引优化实战(3) 知识点:Mysql 数据库索引优化实战(4) 八. 联合索引与覆盖索引 ...
- Linux下自己实现getopt功能
实现思路: 通过 pid_t pid = getpid() 来获取当前进程id,然后 sprintf(fname, "/proc/%d/cmdline", pid); 读取fnam ...
- GPIO输入输出各种模式(推挽、开漏、准双向端口)详解
转自:https://blog.csdn.net/techexchangeischeap/article/details/72569999 概述 能将处理器的GPIO(General Purpose ...
- Linq to SQL -- Insert、Update、Delete
Insert/Update/Delete操作 插入(Insert) 1.简单形式 说明:new一个对象,使用InsertOnSubmit方法将其加入到对应的集合中,使用SubmitChanges()提 ...
- JAVA 8 函数式接口--Consumer
从JDK8开始java支持函数式编程,JDK也提供了几个常用的函数式接口,这篇主要介绍Consumer接口.文本介绍的顺序依次为: 源码介绍 使用实例 jdk内对Consumer的典型使用 扩展类介绍 ...