封装一个Promise.allSettled方法_工作篇

什么是 Promise.allSettled()!新手老手都要会?

Promise.allSettled() 方法返回一个在所有给定的 promise 都已经 fulfilledrejected 后的 promise,并带有一个对象数组,每个对象表示对应的 promise 结果。

接着,我们来看看 Promise.allSettled() 是如何工作的。

1. Promise.allSettled()

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

该函数接受一个 promise 数组(通常是一个可迭代对象)作为参数:

const statusesPromise = Promise.allSettled(promises);

当所有的输入 promises 都被 fulfilledrejected 时,statusesPromise 会解析为一个具有它们状态的数组

  1. { status: &#;fulfilled&#;, value: value } — 如果对应的 promise 已经 fulfilled
  2. 或者 {status: &#;rejected&#;, reason: reason} 如果相应的 promise 已经被 rejected

在解析所有 promises 之后,可以使用 then 语法提取它们的状态:

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

或者使用 async/await 语法:

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

2. 取水果和蔬菜

在深入研究 Promise.allSettle() 之前,我们先定义两个简单的 helper 函数。

首先,resolveTimeout(value, delay)返回一个 promise ,该 promise 在经过 delay 时间后用 value 来实现

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

第二,rejectTimeout(reason, delay) - 返回一个 promise,在经过 delay 时间后拒绝reason

最后,我们使用这些辅助函数来试验 promise.allsettle()

All promises fulfilled

我们同时访问当地杂货店的蔬菜和水果。访问每个列表是一个异步操作:

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

线上事例:https://codesandbox.io/s/all-resolved-yyc0l?file=/src/index.js

Promise.allSettled([...])返回一个 promise statusesPromise,该 promise 在1秒内解决,就在蔬菜和水果被解决之后,并行地解决。

statusesPromise 解析为一个包含状态的数组。

  1. 数组的第一项包含有蔬菜的已完成状态:status: &#;fulfilled&#;, value: [&#;potatoes&#;, &#;tomatoes&#;] }
  2. 同样的方式,第二项是水果的完成状态: { status: &#;fulfilled&#;, value: [&#;oranges&#;, &#;apples&#;] }

一个 promise 被拒绝

想象一下,在杂货店里已经没有水果了。在这种情况下,我们拒绝水果的 promise。

promise.allsettle() 在这种情况下如何工作?

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

线上事例:https://codesandbox.io/s/one-rejected-ij3uo?file=/src/index.js

Promise.allSettled([...]) 返回的 promise 在 1 秒后解析为一个状态数组:

  1. 数组的第一项,蔬菜 promise 成功解析:{ status: &#;fulfilled&#;, value: [&#;potatoes&#;, &#;tomatoes&#;] }
  2. 第二项,因为水果 promise 被拒绝,所以是一个拒绝状态: { status: &#;rejected&#;, reason: Error(&#;Out of fruits&#;) }

即使输入数组中的第二个 promise 被拒绝,statusesPromise仍然会成功解析一个状态数组。

所有的 promises 都被 rejected

如果杂货店里的蔬菜和水果都卖光了怎么办?在这种情况下,两个 promise 都会被拒绝。

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

线上事例:https://codesandbox.io/s/all-rejected-z4jee?file=/src/index.js

在这种情况下,statusesPromise仍然成功地解析为一个状态数组。然而,该数组包含被拒绝的promise 的状态。

3.总结

Promise.allSettled(promises)可以并行地运行 promise,并将状态(fulfilled 或reject)收集到一个聚合数组中。

Promise.allSettled(...)在你需要执行平行和独立的异步操作并收集所有结果时非常有效,即使某些异步操作可能失败。

~~ 完,我是刷碗智,你们的点赞及在看是对我刷碗最大的认可。


作者:Dmitri Pavlutin 译者:小糖 来源:dmitripavluti 原文:https://dmitripavlutin.com/promise-all-settled/

原文链接:,转发请注明来源!