如何在JAVASCRIPT中使用Promise.allSettled()函数教程

293 阅读3分钟

如何使用Promise.allSettled()

Promise.allSettled(promises) 是一个辅助函数,它可以并行地运行承诺,并将已解决的状态(已完成或已拒绝)聚合到一个结果数组中。

让我们看看Promise.allSettled() 如何工作。

1.Promise.allSettled()

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

该函数接受一个数组(或一般是一个可迭代的)的承诺作为参数。

const statusesPromise = Promise.allSettled(promises);

所有的输入promises ,被履行或拒绝,并行地,statusesPromise 解析为一个具有它们状态的数组。

  1. { status: 'fulfilled', value: value } - 如果相应的承诺已经履行了
  2. 或者{ status: 'rejected', reason: reason } - 如果相应的承诺被拒绝。

Promise.allSettled() in JavaScript

在所有的输入promises 被解析后,你可以使用then-able 语法提取它们的状态。

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

或使用async/await 语法。

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

Promise.allSettled() 返回的承诺总是以一个状态数组来实现的,无论一些(甚至所有!)输入的承诺是否被拒绝。

2.取出水果和蔬菜

在深入研究Promise.allSettle() ,让我们定义2个简单的辅助函数。

首先,resolveTimeout(value, delay) - 返回一个承诺,在通过delay 的时间后与value 实现。

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

第二,rejectTimeout(reason, delay) - 返回一个承诺,在通过delay 时间后用reason 拒绝。

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

让我们用这些辅助函数在Promise.allSettled() 上做实验。

2.1 所有承诺的实现

让我们并行地访问当地杂货店里的蔬菜和水果。访问每个列表是一个异步操作。

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

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

该承诺statusesPromise ,解析为一个包含状态的数组。

  1. 数组的第一项包含蔬菜的满足状态。{ status: 'fulfilled', value: ['potatoes', 'tomatoes'] }
  2. 同样地,第二项是水果的完成状态:{ status: 'fulfilled', value: ['oranges', 'apples'] }

2.2 拒绝一个承诺

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

在这种情况下,Promise.allSettled() 将如何工作?

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

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

  1. 数组的第一项,因为蔬菜承诺成功解决,是{ status: 'fulfilled', value: ['potatoes', 'tomatoes'] }
  2. 第二项,因为水果的承诺被错误拒绝,是一个拒绝状态:{ status: 'rejected', reason: Error('Out of fruits') }

即使输入数组中的第二个承诺被拒绝了,statusesPromise ,仍然成功地解决了一个状态数组。

2.3 所有承诺被拒绝

如果杂货店的蔬菜和水果都用完了怎么办?在这种情况下,两个承诺都被拒绝。

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 second
console.log(statuses); 
// [
//   { status: 'rejected', reason: Error('Out of vegetables!')  },
//   { status: 'rejected', reason: Error('Out of fruits!') }
// ]

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

3.结论

Promise.allSettled(promises) 让你并行地运行承诺,并将状态(已完成或拒绝)收集到一个聚合数组中。

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