在现代 JavaScript 开发中,Promise 已成为处理异步操作的核心工具。而在多个异步任务需要并发执行时,Promise 提供了多种组合方法,其中 Promise.all、Promise.allSettled 和 Promise.any 是最常用的三种。理解它们的差异与使用场景,可以显著提升代码健壮性与执行效率。
本文将系统讲解三者的用法、区别以及实际应用场景。
Promise.all:全部成功才算成功
Promise.all() 用于并发执行多个异步任务,并在 所有任务成功完成后 返回结果。它接收一个可迭代对象(通常是 Promise 数组),并返回一个新的 Promise。
执行规则:
- 所有 Promise 成功 → 返回结果数组
- 任意 Promise 失败 → 立即 reject(快速失败)
- 结果顺序与输入顺序一致,而非完成顺序
示例:
const p1 = Promise.resolve(1);
const p2 = Promise.resolve(2);
const p3 = Promise.resolve(3);
Promise.all([p1, p2, p3])
.then(res => console.log(res));
// 输出: [1, 2, 3]
如果其中一个失败:
Promise.all([
Promise.resolve("OK"),
Promise.reject("Error"),
Promise.resolve("Done")
]).catch(err => console.log(err));
// 输出: Error
适用场景:
- 页面初始化必须加载完所有数据
- 多个接口结果缺一不可
- 资源全部加载成功才继续执行
优点是执行效率高,但缺点是只要一个失败就会整体失败。
Promise.allSettled:获取所有任务结果
Promise.allSettled() 会等待所有 Promise 执行完成,无论成功还是失败,最终返回每个任务的状态结果。
返回结果格式:
- status: "fulfilled" 或 "rejected"
- value: 成功结果
- reason: 失败原因
示例:
Promise.allSettled([
Promise.resolve("成功"),
Promise.reject("失败")
]).then(results => console.log(results));
输出:
[
{ status: "fulfilled", value: "成功" },
{ status: "rejected", reason: "失败" }
]
特点:
- 永远不会 reject
- 返回每个任务的执行状态
- 适合部分成功也可接受的场景
适用场景:
- 批量上传文件,失败的重试
- 多接口请求展示部分数据
- 统计任务执行结果
- 日志收集与监控系统
Promise.any:第一个成功即返回
Promise.any() 会返回 第一个成功(fulfilled)的 Promise 结果,并忽略失败的 Promise。
如果所有 Promise 都失败,则会抛出 AggregateError,其中包含所有错误信息。
示例:
Promise.any([
Promise.reject("错误1"),
Promise.resolve("成功"),
Promise.resolve("成功2")
]).then(res => console.log(res));
// 输出: 成功
全部失败示例:
Promise.any([
Promise.reject("错误1"),
Promise.reject("错误2")
]).catch(err => console.log(err.errors));
特点:
- 返回第一个成功结果
- 忽略失败直到成功出现
- 全部失败才报错
适用场景:
- 多个 CDN 资源请求,选最快可用
- 多服务器接口容灾
- 备用数据源回退机制
- 搜索多个节点返回最快结果
三者核心区别对比
Promise.all
- 全部成功才成功
- 一个失败立即失败
- 返回成功数组
Promise.allSettled
- 等待全部完成
- 永不失败
- 返回状态对象数组
Promise.any
- 第一个成功即返回
- 全部失败才报错
- 返回单个成功结果
如何选择合适的方法?
如果任务必须全部成功,使用 Promise.all。
如果需要知道每个任务结果,使用 Promise.allSettled。
如果只需要一个成功结果,使用 Promise.any。
实际开发中的最佳实践
在真实项目中,这三个方法往往组合使用:
- 页面核心数据:Promise.all
- 辅助数据加载:Promise.allSettled
- 容灾与备用接口:Promise.any
合理选择可以避免接口失败导致页面崩溃,同时提升用户体验。
结语
Promise.all、Promise.allSettled 和 Promise.any 是处理并发异步任务的重要工具。掌握它们的行为差异与应用场景,不仅能提升代码可靠性,还能优化系统性能与容错能力。
在复杂异步场景中,选择正确的方法往往比优化代码更重要。