创见博客
Promise的四个静态方法(all/allSettled/)
七崽爱吃小饼干2026/01/29阅读 3专栏 JavaScript

Promise 的 all、allSettled、race、any 这四个静态方法都用于处理多个 Promise 组成的数组(可迭代对象),返回值都是一个全新的 Promise,但它们的「触发成功/失败的条件」和「返回结果格式」有本质区别。


1. Promise.all():「全部成功才成功,一个失败就失败」

功能说明

  • 接收一个 Promise 可迭代对象(通常是数组)。
  • 只有所有 Promise 都变为 fulfilled(成功),返回的新 Promise 才会成功。
  • 只要有一个 Promise 变为 rejected(失败),就会立即触发返回 Promise 的失败,且不会等待其他 Promise 执行完成(「快速失败」特性)。
  • 成功返回的结果是一个数组,数组中结果的顺序和传入 Promise 数组的顺序完全一致(和执行完成顺序无关)。

代码示例

javascript
// 定义三个模拟 Promise
const p1 = Promise.resolve("结果1");
const p2 = new Promise((resolve) => setTimeout(() => resolve("结果2"), 1000));
const p3 = Promise.resolve("结果3");

// 正常情况:所有 Promise 都成功
Promise.all([p1, p2, p3])
  .then((result) => {
    console.log("all 成功结果:", result); // 输出:all 成功结果: ['结果1', '结果2', '结果3']
  })
  .catch((error) => {
    console.log("all 失败结果:", error);
  });

// 异常情况:有一个 Promise 失败
const p4 = Promise.reject("出错了!");
Promise.all([p1, p4, p2])
  .then((result) => {
    console.log("all 成功结果:", result);
  })
  .catch((error) => {
    console.log("all 失败结果:", error); // 立即输出:all 失败结果: 出错了!(不会等待 p2 执行)
  });

适用场景

需要等待多个异步操作全部完成后,再执行后续逻辑,且其中任何一个操作失败都无法继续的场景。 例如:提交表单前,需要同时获取用户信息、验证手机号、检查权限,三个接口都成功才能提交。


2. Promise.allSettled():「无论成败,全部等待完成」

功能说明

  • 接收一个 Promise 可迭代对象。
  • 无论传入的 Promise 是成功还是失败,都会等待所有 Promise 执行完成(无「快速失败」特性)。
  • 返回的新 Promise 永远是成功状态,成功结果是一个对象数组,每个对象对应一个传入的 Promise,包含两个属性:
    • status:Promise 状态(fulfilled 成功 / rejected 失败)。
    • value:status 为 fulfilled 时,对应的 Promise 成功结果(可选)。
    • reason:status 为 rejected 时,对应的 Promise 失败原因(可选)。

代码示例

javascript
const p1 = Promise.resolve("结果1");
const p2 = new Promise((resolve) => setTimeout(() => resolve("结果2"), 1000));
const p3 = Promise.reject("出错了!");

Promise.allSettled([p1, p2, p3])
  .then((result) => {
    console.log("allSettled 结果:", result);
    // 输出结果(数组顺序和传入顺序一致):
    // [
    //   { status: 'fulfilled', value: '结果1' },
    //   { status: 'fulfilled', value: '结果2' },
    //   { status: 'rejected', reason: '出错了!' }
    // ]
  });

适用场景

需要获取所有异步操作的完整结果(成功/失败都要),不希望某个操作失败中断其他操作的场景。 例如:页面加载时,同时请求多个非核心接口(广告、推荐、统计),无论哪个接口失败,都要展示其他接口的返回结果。


3. Promise.race():「谁先完成,就用谁的结果(无论成败)」

功能说明

  • 接收一个 Promise 可迭代对象。
  • 「竞赛」模式:只要有一个 Promise 率先完成(无论成功 fulfilled 还是失败 rejected),就立即采用该 Promise 的结果。
  • 返回的新 Promise 状态和率先完成的那个 Promise 一致:
    • 率先完成的是成功,返回的 Promise 就成功。
    • 率先完成的是失败,返回的 Promise 就失败。
  • 只返回第一个完成的 Promise 的结果,忽略其他所有后续完成的 Promise。

代码示例

javascript
// 定义三个模拟 Promise(执行速度不同)
const p1 = new Promise((resolve) => setTimeout(() => resolve("结果1"), 1000)); // 1秒后成功
const p2 = new Promise((resolve, reject) => setTimeout(() => reject("出错了!"), 500)); // 0.5秒后失败
const p3 = Promise.resolve("结果3"); // 立即成功

// 场景1:p3 立即完成,返回 p3 的成功结果
Promise.race([p1, p2, p3])
  .then((result) => {
    console.log("race 成功结果:", result); // 输出:race 成功结果: 结果3
  })
  .catch((error) => {
    console.log("race 失败结果:", error);
  });

// 场景2:注释 p3,p2 先完成(失败),返回 p2 的失败结果
// Promise.race([p1, p2])
//   .then((result) => {
//     console.log("race 成功结果:", result);
//   })
//   .catch((error) => {
//     console.log("race 失败结果:", error); // 输出:race 失败结果: 出错了!
//   });

适用场景

需要给异步操作设置超时时间,或者只需要获取多个异步操作中「最快返回」的结果的场景。 例如:接口请求时,超过5秒还未返回,就提示「请求超时」(用 Promise.race 包装接口 Promise 和一个 5 秒后失败的 Promise)。


4. Promise.any():「谁先成功,就用谁的结果;全部失败才失败」

功能说明

  • 接收一个 Promise 可迭代对象。
  • 「容错竞赛」模式:忽略失败的 Promise,只等待第一个成功的 Promise。
  • 返回的新 Promise 状态规则:
    1. 只要有一个 Promise 成功,就立即采用该成功结果(返回成功的 Promise)。
    2. 只有所有 Promise 都失败,才会返回失败的 Promise,失败原因是一个 AggregateError(包含所有失败原因的集合)。
  • 对比 race:any 只关心「第一个成功」,race 关心「第一个完成(无论成败)」。

代码示例

javascript
const p1 = new Promise((resolve) => setTimeout(() => resolve("结果1"), 1000)); // 1秒后成功
const p2 = new Promise((resolve, reject) => setTimeout(() => reject("出错了!"), 500)); // 0.5秒后失败
const p3 = Promise.reject("又出错了!"); // 立即失败

// 场景1:p2、p3 先失败,最终 p1 成功,返回 p1 的结果
Promise.any([p1, p2, p3])
  .then((result) => {
    console.log("any 成功结果:", result); // 输出:any 成功结果: 结果1
  })
  .catch((error) => {
    console.log("any 失败结果:", error);
    console.log("any 所有失败原因:", error.errors); // 查看所有失败原因
  });

// 场景2:所有 Promise 都失败,返回 AggregateError
// const p4 = Promise.reject("错误1");
// const p5 = Promise.reject("错误2");
// Promise.any([p4, p5])
//   .then((result) => {
//     console.log("any 成功结果:", result);
//   })
//   .catch((error) => {
//     console.log("any 失败结果:", error); // 输出:AggregateError: All promises were rejected
//     console.log("any 所有失败原因:", error.errors); // 输出:['错误1', '错误2']
//   });

适用场景

需要从多个异步操作中获取「任意一个成功结果」,且希望容错(部分操作失败不影响)的场景。 例如:请求同一个接口的多个备用节点(主节点、备用节点1、备用节点2),只要有一个节点返回成功,就使用该结果,无需等待其他节点。


核心对比表格

为了方便你快速记忆,整理了关键属性对比表:

方法名成功条件失败条件结果格式快速失败适用场景
Promise.all所有 Promise 都成功任意一个 Promise 失败成功结果数组(顺序对应)是需所有异步操作完成才能继续
Promise.allSettled永远成功(无论传入结果)无(返回的 Promise 永不失败)状态对象数组(包含成功/失败)否需获取所有异步操作的完整结果
Promise.race第一个完成的 Promise 成功第一个完成的 Promise 失败第一个完成的 Promise 结果是异步操作超时控制、取最快结果
Promise.any任意一个 Promise 成功(第一个成功)所有 Promise 都失败第一个成功的 Promise 结果否(忽略失败)多备用节点请求、容错取成功结果

总结

  1. 需全部成功用 all,需全部结果(无论成败)用 allSettled。
  2. 需最快完成(无论成败)用 race,需最快成功(容错失败)用 any。
  3. 四个方法返回的都是新 Promise,且结果顺序(除 race/any 只取第一个外)与传入 Promise 数组顺序一致。
评论
0/100