并行执行多个独立的异步操作 - Promise.allSettled()

<!-- TOC -->

  • 并行执行多个独立的异步操作 - Promise.allSettled()

    • 介绍
    • 如何应用Promise.allSettled()

      • 1.Promise.allSettled()
      • 2. example: 简略的应用Promise.allSettled()

        • 2.1. 所有promise已实现
        • 2.2 某个promise已回绝
        • 2.3 所有promise已回绝
    • 小结:
    • 兼容性:
    • 参考
    • 动下小手

<!-- /TOC -->

介绍

Promise.allSettled(promises) 是一个辅助函数,它并行运行 Promise, 并将已扭转的状态(已实现或已回绝)寄存到一个数组中,返回给开发者应用。

当您有多个彼此不依赖(或者是说互相独立的)的异步工作,您想晓得每一个promise工作的执行后果的时候(无论是已实现或已回绝),通常应用它。

让咱们看看 Promise.allSettled() 是如何应用的。

如何应用Promise.allSettled()

1.Promise.allSettled()

Promise.allSettled() 可用于并行执行独立异步操作,并收集这些异步操作实现的后果。

该函数承受一个 Promise 数组(或通常是一个可迭代的)作为参数:

const statusesPromise = Promise.allSettled(promises);

当咱们传入的参数promises数组中,每一项产生了状态的扭转(无论是已实现或已回绝)之后,Promise.allSettled都会将promises数组中每一项的执行后果,给咱们寄存在一个数组中,返回给开发者应用。

返回的数组statusesPromise中每一项的的格局如下:

  1. { status: 'fulfilled', value: value } — 如果对应的 promise 已实现
    或者
  2. { status: 'rejected', reason: reason } — 如果相应的 promise 已回绝

当所有的promise都被resolved 或是 被rejected后,你能够应用.then对他们进行后续的操作:

statusesPromise.then(statuses => { statuses; // [{ status: '...', value: '...' }, ...]});

或者应用 async/await 对他们进行后续操作:

const statuses = await statusesPromise;statuses; // [{ status: '...', value: '...' }, ...]

2. example: 简略的应用Promise.allSettled()

在理解 Promise.allSettle() 之前,让咱们定义 2 个简略的辅助函数:

首先,resolveTimeout(value, delay) —— 返回一个promise, 这个promise会在一段时间之后,触发resolve函数:

function resolveTimeout(value, delay) {  return new Promise(    resolve => setTimeout(() => resolve(value), delay)  );}

其次,rejectTimeout(reason, delay)——返回一个promise,这个promise会在一段时间之后,触发reject函数:

function rejectTimeout(reason, delay) {  return new Promise(    (r, reject) => setTimeout(() => reject(reason), delay)  );}

咱们就应用这两个辅助函数来试验下 Promise.allSettled() 的性能吧。

2.1. 所有promise已实现

上面,我会去同时执行一些异步的操作:

const statusesPromise = Promise.allSettled([  resolveTimeout(['potatoes', 'tomatoes'], 1000),  resolveTimeout(['oranges', 'apples'], 1000)]);// wait...const statuses = await statusesPromise;// after 1 secondconsole.log(statuses); // [//   { status: 'fulfilled', value: ['potatoes', 'tomatoes'] },//   { status: 'fulfilled', value: ['oranges', 'apples'] }// ]

Promise.allSettled([...]) 返回一个数组 statusesPromise,两个异步操作都是并行执行的。
statusesPromisePromise.allSettled([...]) 返回的一个数组,数组中的每一项都蕴含了对应的异步操作执行实现之后的状态:

  1. 数组statusesPromise的第一项蕴含了实现状态:{ status: 'fulfilled', value: ['potatoes', 'tomatoes'] }
    同样,
  2. 数组statusesPromise的第二项蕴含了实现状态:{ status: 'fulfilled', value: ['oranges', 'apples'] }。

2.2 某个promise已回绝

如果在多个并行独立的异步操作中,有一个异步操作是已回绝的,那么Promise.allSettled([...])会怎么解决呢?

const statusesPromise = Promise.allSettled([  resolveTimeout(['potatoes', 'tomatoes'], 1000),  rejectTimeout(new Error('Out of fruits!'), 1000)]);// wait...const statuses = await statusesPromise;// after 1 secondconsole.log(statuses); // [//   { status: 'fulfilled', value: ['potatoes', 'tomatoes'] },//   { status: 'rejected', reason: Error('Out of fruits!') }// ]

我看下后果,咱们会很快明确:

  1. 第一项因为触发了resolve函数,promise是已实现,数组的第一项是 { status: 'fulfilled', value: ['potatoes', 'tomatoes'] }
  2. 第二项因为是触发reject函数,promise是已回绝,数组的第二项状态被批改为rejected状态:{ status: 'rejected', reason: Error('Out of Fruits') }。

即便是有某一项是转变为rejected状态, 然而最初Promise.allSettled函数是会蕴含这一项,就它寄存在返回值中。

2.3 所有promise已回绝

咱们看下如下代码:

const statusesPromise = Promise.allSettled([  rejectTimeout(new Error('Out of vegetables!'), 1000),  rejectTimeout(new Error('Out of fruits!'), 1000)]);// wait...const statuses = await statusesPromise;// after 1 secondconsole.log(statuses); // [//   { status: 'rejected', reason: Error('Out of vegetables!')  },//   { status: 'rejected', reason: Error('Out of fruits!') }// ]

在这种状况下, Promise.allSettled依然会返回一个数组。 只是,该数组中每一项的状态都是rejected状态。

小结:

Promise.allSettled(promises) 容许您并行执行相互独立的promise, 并每一个promise执行之后的状态(已实现或回绝)寄存在数组中。

当您须要执行并行和独立的异步操作并获取到异步操作的所有后果时,Promise.allSettled(...) 十分有用,即便某些异步操作可能会失败。

兼容性:

参考: 兼容性 很好

参考

  • TC39:Promise.allSettled
  • MDN: Promise.allSettled()

动下小手

  • 欢送关注我的GitHub:@huangyangquang ⭐⭐
  • 欢送关注我的公众号:前端学长Joshua
    <img src="http://qvf3q8r5e.hn-bkt.clouddn.com/wechatQrCode.jpg" width="50%">