all() 与 allSettled() 深度解析在 JavaScript 异步编程中,处理多个 Promise 是常见的需求。Promise 对象提供了几个强大的静态方法来管理这些并发任务,其中最常用的是 Promise.all() 和 Promise.allSettled()。
虽然它们都用于等待一组 Promise 完成,但在错误处理机制和返回值结构上存在根本差异,适用于不同的业务场景。
Promise.all():全有或全无(Fail-fast)Promise.all() 是最经典的并发控制方法,它要求所有传入的 Promise 必须成功(resolve)才能成功。
| 特性 | 说明 |
|---|---|
| 错误处理 | 快速失败 (Fail-fast):只要输入数组中有一个 Promise 被拒绝(reject),Promise.all() 就会立即返回一个被拒绝的 Promise,并携带第一个拒绝的原因。它不会等待其余未完成的 Promise。 |
| 返回值 | 如果全部成功,返回一个 Promise,该 Promise 解决为一个值的数组,数组顺序与输入 Promise 的顺序一致。 |
| 适用场景 | 任务之间存在强依赖关系,任何一个任务的失败都将导致整个后续操作无法进行。 |
// 假设 fnA 成功,fnB 失败
const promiseA = Promise.resolve('数据 A');
const promiseB = Promise.reject(new Error('B 任务失败'));
const promiseC = new Promise(res => setTimeout(() => res('数据 C'), 5000)); // 耗时任务
async function usePromiseAll() {
try {
// promiseB 立即失败,Promise.all 会立刻拒绝,promiseC 不会被等待。
const results = await Promise.all([promiseA, promiseB, promiseC]);
console.log('成功结果:', results); // 不会执行
} catch (error) {
console.error('错误原因:', error.message);
// 输出: "错误原因: B 任务失败"
}
}
// usePromiseAll();
Promise.allSettled():坚如磐石(Wait-for-all)Promise.allSettled() 是 ES2020 引入的方法,它设计的初衷是为了确保无论 Promise 成功或失败,都能获取所有任务的结果。
| 特性 | 说明 |
|---|---|
| 错误处理 | 永不失败:它总是等待所有传入的 Promise 都达到“敲定”(Settled)状态,即全部完成(无论是 fulfilled 还是 rejected)。它返回的 Promise 永远会成功解决。 |
| 返回值 | 返回一个 Promise,该 Promise 解决为一个结果对象的数组,数组中每个对象描述了对应 Promise 的最终状态和值/原因。 |
| 适用场景 | 任务之间互相独立,需要确保所有任务都执行完毕,并且需要获取每个任务的具体成功或失败信息。 |
// 假设 fnA 成功,fnB 失败
const promiseA = Promise.resolve('数据 A');
const promiseB = Promise.reject(new Error('B 任务失败'));
const promiseC = new Promise(res => setTimeout(() => res('数据 C'), 5000));
async function usePromiseAllSettled() {
// 即使 promiseB 失败,await 也会等待 promiseA, B, C 全部完成
const results = await Promise.allSettled([promiseA, promiseB, promiseC]);
console.log('全部结果:', results);
/* 输出:
[
{ status: 'fulfilled', value: '数据 A' },
{ status: 'rejected', reason: [Error: B 任务失败] },
{ status: 'fulfilled', value: '数据 C' }
]
*/
// 优雅地处理结果
const successfulResults = results
.filter(p => p.status === 'fulfilled')
.map(p => p.value);
console.log('成功的数据:', successfulResults);
}
// usePromiseAllSettled();
| 特性 | Promise.all() | Promise.allSettled() |
|---|---|---|
| 是否会失败 | 是(只要有一个 Promise 拒绝,它就会失败) | 否(永远成功解决) |
| 等待机制 | 快速失败,不等待失败后的 Promise | 等待所有 Promise 完成(成功或失败) |
| 返回值结构 | 纯粹的值数组 [value1, value2, ...] | 状态对象数组 [{status: 'fulfilled', value: ...}, {status: 'rejected', reason: ...}] |
| 适用场景 | 必须全部成功(例如:加载多个依赖配置文件) | 需要获取所有任务结果,并容忍部分失败(例如:发送多条不相关日志/通知) |
在选择使用哪个方法时,请问自己:“如果这些并发任务中有一个失败了,我的程序还能继续进行吗?”
Promise.all()。Promise.allSettled()。