如何使用Promise.allSettled()
Promise.allSettled(promises) 是一个辅助函数,它可以并行地运行承诺,并将已解决的状态(已完成或已拒绝)聚合到一个结果数组中。
让我们看看Promise.allSettled() 如何工作。
1.Promise.allSettled()
Promise.allSettled() 对于并行执行独立的异步操作,并收集这些操作的结果,是非常有用的。
该函数接受一个数组(或一般是一个可迭代的)的承诺作为参数。
const statusesPromise = Promise.allSettled(promises);
当所有的输入promises ,被履行或拒绝,并行地,statusesPromise 解析为一个具有它们状态的数组。
{ status: 'fulfilled', value: value }- 如果相应的承诺已经履行了- 或者
{ status: 'rejected', reason: reason }- 如果相应的承诺被拒绝。
在所有的输入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 ,解析为一个包含状态的数组。
- 数组的第一项包含蔬菜的满足状态。
{ status: 'fulfilled', value: ['potatoes', 'tomatoes'] } - 同样地,第二项是水果的完成状态:
{ 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秒后解析为一个状态数组。
- 数组的第一项,因为蔬菜承诺成功解决,是
{ status: 'fulfilled', value: ['potatoes', 'tomatoes'] } - 第二项,因为水果的承诺被错误拒绝,是一个拒绝状态:
{ 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(...) 当你需要执行平行和独立的异步操作,并收集所有的结果时,即使一些异步操作可能会失败,这个方法非常有效。