Promise.all适用于所有任务必须成功才继续的场景,它等待全部fulfilled后返回结果数组,任一rejected则立即reject;而Promise.allSettled用于容错收集,返回每个任务的status和value/reason。

Promise.all 适合所有任务必须成功才继续
当多个异步操作彼此独立,且你只关心「全部完成」的结果时,Promise.all 是最直接的选择。它会等待所有 Promise 都 fulfilled 才返回结果数组;只要有一个 rejected,就立刻 reject 并抛出第一个失败的错误。
常见错误现象:Promise.all 中某个请求 404 或超时,整个链路中断,后续逻辑拿不到任何数据。
- 使用场景:批量获取用户资料、并行加载多个模块、表单提交前校验多项远程字段
- 注意
Promise.all返回的数组顺序严格对应输入顺序,和执行完成时间无关 - 如果某项 Promise 可能失败但你不希望中断整体流程,得先用
.catch(() => null)拦截,或改用Promise.allSettled
const promises = [
fetch('/api/user/1').then(r => r.json()),
fetch('/api/user/2').then(r => r.json()),
fetch('/api/user/3').then(r => r.json())
];
Promise.all(promises)
.then(results => console.log(results)) // [user1, user2, user3]
.catch(err => console.error('任一请求失败:', err));
Promise.allSettled 更适合“容错收集”场景
Promise.allSettled 不会在某个 Promise 失败时中断,而是等全部 settle(fulfilled 或 rejected)后,返回每个任务的状态对象数组。这是处理「部分失败可接受」任务的核心方法。
容易踩的坑:误以为 allSettled 返回的是原始值数组,其实每个元素是 { status: 'fulfilled' | 'rejected', value | reason } 结构。
- 使用场景:日志上报、多端同步、灰度发布验证、批量接口健康检查
- 性能影响几乎为零——它和
all底层调度机制一致,只是语义不同 - 兼容性注意:Node.js 12.9+ / Chrome 76+ / Firefox 71+ 支持;旧环境需 polyfill 或降级为
all+catch包装
const promises = [
Promise.resolve(42),
Promise.reject(new Error('oops')),
Promise.resolve('hello')
];
Promise.allSettled(promises).then(results => {
results.forEach((r, i) => {
if (r.status === 'fulfilled') {
console.log(`第${i}项成功:`, r.value);
} else {
console.log(`第${i}项失败:`, r.reason.message);
}
});
});
Promise.race 和 Promise.any 容易被误用
Promise.race 返回第一个 settled 的结果(无论 fulfilled 还是 rejected),常被误当成「取最快响应」的万能方案。但它一旦遇到网络抖动导致某个请求秒 reject,就会提前终止整个流程。
分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。
Promise.any 则只关心第一个 fulfilled,其余 rejected 被忽略(除非全 rejected 才 throw AggregateError)。它比 race 更安全,但支持度更低(Node.js 16+ / Chrome 89+)。
- 真正适合
race的场景:带超时控制的请求封装(如Promise.race([fetch(...), timeout(5000)])) -
any典型用途:从多个 CDN 源并发加载资源,只要一个成功即可 - 别在没有兜底逻辑时直接用
race处理业务 API,它太脆弱
链式调用中混用 async/await 和 Promise 方法要小心
async 函数内部用 await Promise.all([...]) 很自然,但若在 .then() 链里又嵌套 async 回调,容易产生未处理的 rejected Promise(尤其忘记加 .catch)。
关键判断点:是否需要按顺序执行?是否允许并发?失败是否可跳过?这些决定了该用串行 for...of + await、还是并发 all/allSettled、还是带重试的自定义封装。
- 不要写
promises.map(p => p.then(...))后再传给Promise.all——这会让错误丢失上下文 - 避免在循环中无节制创建 Promise(如 1000 个并发请求),应考虑分批或加节流
- 复杂流程建议封装成函数,比如
runInBatches(promises, 10),而不是堆砌原生 API
实际项目里,多数「多个异步任务」的需求既不是全要成功,也不是只看最快,而是需要明确区分哪些失败可容忍、哪些必须阻断、哪些要重试——选对 API 只是第一步,关键是把业务语义映射到 Promise 状态机上。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










