|

Promise.all、Promise.allSettled、Promise.any 用法详解:JavaScript 并发处理指南

在现代 JavaScript 开发中,Promise 已成为处理异步操作的核心工具。而在多个异步任务需要并发执行时,Promise 提供了多种组合方法,其中 Promise.all、Promise.allSettled 和 Promise.any 是最常用的三种。理解它们的差异与使用场景,可以显著提升代码健壮性与执行效率。

本文将系统讲解三者的用法、区别以及实际应用场景。

Promise.all:全部成功才算成功

Promise.all() 用于并发执行多个异步任务,并在 所有任务成功完成后 返回结果。它接收一个可迭代对象(通常是 Promise 数组),并返回一个新的 Promise。

执行规则:

  1. 所有 Promise 成功 → 返回结果数组
  2. 任意 Promise 失败 → 立即 reject(快速失败)
  3. 结果顺序与输入顺序一致,而非完成顺序

示例:

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 是处理并发异步任务的重要工具。掌握它们的行为差异与应用场景,不仅能提升代码可靠性,还能优化系统性能与容错能力。

在复杂异步场景中,选择正确的方法往往比优化代码更重要。

评论