从零开始学

xiaoxiao2021-02-28  101

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和4foo的值被第一个执行了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对象。

转载请注明原文地址: https://www.6miu.com/read-850136.html

最新回复(0)