从零开始学_JavaScript_系列(50)——Promise(3)全部完成all和看谁最快race
2017-07-28 10:10
585 查看
7、全部完成才结束Promise.all
场景我们在写ajax的时候,经常会面临这样一个场景:
我有三个ajax请求,但是需要等着三个ajax的请求结果都出来后再进行处理。
如果常见写法,我们需要在每个都执行完之后,依次判断一下其他的完成了没有,完成了才能继续,没完成就return。
但是使用
Promise.all的话,问题简单多了。
Promise.all(iterable);
参数:
一般是一个数组,也可以是一个有迭代器接口的对象,但要求每个成员都是Promise实例。
返回值:
是一个Promise对象,为了方便称之为foo。
返回值的状态将维持pending不变,直到当参数的每个Promise实例的状态从pending变化为resolved,或者rejected时。
返回值Promise对象的变化规则:
1、参数的所有Promise都执行resolve,那么结果:
foo的状态resolved;
foo的then执行resolve;
foo的值是一个数组;
参数里的Promise对象的值按顺序(迭代器里的顺序,而非状态变化顺序)被放入到这个数组中,作为foo的值使用;
2、假如参数里的Promise对象有一个执行了reject,那么结果:
foo的状态rejected;
foo的then执行reject;
foo的值被执行了reject的那个Promise对象所决定;
foo的reject将在那个执行了reject的Promise对象执行后立刻执行(而不是等所有的都执行完毕);
3、假如参数中的Promise对象有多个执行了reject,那么结果:
同上一种情况的1、2和4
foo的值被第一个执行了reject的那个Promise对象所决定(后面的对其无影响);
情况一示例代码:
function delay(msg, time, isRej) { return new Promise((res, rej) => { setTimeout(() => { isRej ? rej(msg) : res(msg) }, time) }) } let promiseArray = [delay("first", 500), delay("second", 3000), delay("third", 1000)]; let foo = Promise.all(promiseArray); foo.then(msg => { console.log(msg) }, err => { console.log(err) }) // ["first", "second", "third"] //3秒后
情况三示例代码(情况二可以参考情况三的,基本是一样的):
function delay(msg, time, isRej) { return new Promise((res, rej) => { setTimeout(() => { isRej ? rej(msg) : res(msg) }, time) }) } let promiseArray = [delay("first", 500), delay("second", 5500, true), delay("third", 1000, true)]; let foo = Promise.all(promiseArray); foo.then(msg => { console.log(msg) }, err => { console.log(err) }) // third //1秒后
另外由于Promise.all的返回值也是一个Promise实例,因此适用于Promise实例的方法,自然也适用于它。
关于参数,更复杂的情况
假如
Promise.all的参数,不是一个单纯的
new Promise()对象,而是
(new Promise()).then(() => {})这样的,会发生什么事情呢?
首先,Promise.all执行哪个,不取决于第一个new Promise()里的状态,而是取决于
.then()执行之后的状态。
原因在于,
(new Promise()).then(() => {})这个表达式的值,是作为
Promise.all()的参数的。
而这个表达式的值,取决于
.then()的值,而这个值,和
new Promise()并不是同一个Promise对象(参照本博客前几章)。
因此假如new Promise()执行了reject,而then里的reject执行了resolve,那么最终结果还是resolved,而不是rejected。
8、谁快用谁的Promise.race
Promise.race(iterable);参数:
同Promise.all,懒得解释了。
返回值:
也是一个Promise对象,为了方便称之为foo。
返回值变化规律:
简单来说,参数的所有Promise对象,哪个的状态最先变化,返回值foo就使用它的。
例如:
参数里有三个Promise对象;
他们状态变化所需要时间分别是2秒,1秒,3秒;
他们的状态变化结果分别是resolved,resolved,rejected;
他们的值分别为’A’, ‘B’,’C’;
Promise.race执行,等1秒后,第二个Promise对象的状态变为resolved;
此时foo的状态立刻变为resolved,执行resolve,值为’B’;
另外两个的状态变化将不能影响foo;
如示例代码:
function delay(msg) { let isFailed = Math.random() > 0.5; let time = parseInt(Math.random() * 1000); return new Promise((res, rej) => { setTimeout(() => { let data = { msg, time, state: 'isFailed? ' + isFailed } isFailed ? rej(data) : res(data) }, time) }) } let promiseArray = [delay("first"), delay("second"), delay("third")]; let foo = Promise.race(promiseArray); foo.then(data => { console.log(data.msg, data.time, data.state) }, data => { console.log(data.msg, data.time, data.state) }) // 因为是随机结果,所以下面是随机结果之一 // second 207 isFailed? true
应用场景:
比如说你请求一个东西,但不想等待时间太久,比如说超过3秒钟就停止请求报告请求失败。
那么就可以使用这个,然后写一个Promise对象,3秒后执行reject的那种,作为最后一个参数。
然后只要超时,就自动执行,然后就ok了。
如示例:
function preventTimeout(promise) { let timeout = new Promise((res, rej) => { setTimeout(() => { rej('超时了!') }, 3000) }) return Promise.race([promise, timeout]) } let foo = new Promise((res, rej) => { setTimeout(() => { res("foo") }, 4000); }) let bar = preventTimeout(foo) bar.then(null, val => { console.log(val) }) // 超时了! //3秒后
将需要进行超时检测的Promise对象,作为preventTimeout函数的参数,然后取用其返回值用于替代使用被检测的Promise对象。
相关文章推荐
- [javascript高手之路] es6系列教程 - promise常见用法详解(resolve,reject,catch,then,all,race)
- [js高手之路] es6系列教程 - promise常见用法详解(resolve,reject,catch,then,all,race)
- 从零开始学_JavaScript_系列(48)——Promise(1)基础知识
- 从零开始学_JavaScript_系列(49)——Promise(2)then、值、catch
- 从零开始学_JavaScript_系列(51)——Promise(4)Promise.resolve和Promise.reject
- 从零开始学_JavaScript_系列(29)——apply和call
- Provisioning Services 7.8 入门系列教程14篇全部完成了.....
- 从零开始学_JavaScript_系列(26)——只需要前端知识的ajax教程
- 从零开始学_JavaScript_系列(65)——class的继承(2)super、extends与多重继承
- 从零开始学_JavaScript_系列(66)——AMD、CMD、CommonJS
- 从零开始学_JavaScript_系列(十一)——dojo(5)(GRID表格进阶:更新值,name,重置表结构/缓存,重绘表格)
- 从零开始学_JavaScript_系列(十一)——dojo(4)(GRID表格进阶:格式化、style、数据获取、多重排序、点击事件)
- 从零开始学_JavaScript_系列(34)——将canvas获取的图片下载到本地
- 从零开始学_JavaScript_系列(58)——Thunk函数
- 从零开始学_JavaScript_系列(七)——jquery(复选框及互斥、div块、修改css、标签数组、ajax连续加载)
- 从零开始学_JavaScript_系列(18)——dojo(7)(dojo中类的继承)
- 深入理解JavaScript系列(50):Function模式(下篇)
- 从零开始学_JavaScript_系列(26)——dojo的aspect方法
- 从零开始学_JavaScript_系列(27)——dojo的文档相关模块
- 从零开始学_JavaScript_系列(35)——继承与遍历的对照表