基于本文回答

播面 播面

文图音视,全方位拆解八股文
0
评论

Promise.all、Promise.race 和 Promise.allSettled 的区别

知识点图片

Promise.allPromise.racePromise.allSettled 都是 JavaScript 中用于处理多个 Promise 并发的方法。它们都接收一个 Promise 可迭代对象(通常是数组),但它们在何时改变状态(resolve/reject)以及返回的结果上有显著的区别。

为了方便理解,我们可以用通俗的比喻来解释,并结合代码和表格进行对比。


1. Promise.all() —— “一票否决”

比喻:团队合作完成一个项目,必须所有人都完成任务,项目才算成功;只要有一个人搞砸了,整个项目直接宣告失败。

  • 执行机制:等待数组中所有的 Promise 都变为 fulfilled(成功)状态,它才会成功。
  • 成功返回值:返回一个数组,包含所有 Promise 的成功结果,且顺序与传入时的顺序完全一致
  • 失败机制:只要数组中有一个 Promise 变为 rejected(失败),Promise.all 就会立即失败(短路效应),并返回第一个失败的 Promise 的错误信息。其他还在执行的 Promise 依然会继续执行,但它们的结果会被忽略。
  • 适用场景:多个并发请求彼此依赖,必须全部成功才能进行下一步(例如:获取用户信息和用户权限都成功后,才渲染页面)。

代码示例

javascript
const p1 = Promise.resolve('成功 1');
const p2 = Promise.resolve('成功 2');
const p3 = Promise.reject('失败 3');

// 全部成功的情况
Promise.all([p1, p2]).then(res => console.log(res)); 
// 输出: ['成功 1', '成功 2']

// 包含失败的情况
Promise.all([p1, p2, p3])
  .then(res => console.log(res))
  .catch(err => console.log(err)); 
// 输出: '失败 3' (因为 p3 失败了,直接走 catch)

2. Promise.race() —— “百米赛跑”

比喻:几个人赛跑,谁第一个冲过终点(无论他是正常跑完还是中途摔倒出局),比赛就结束,结果以这个第一名为准。

  • 执行机制:谁执行得最快,就返回谁的结果。
  • 成功/失败机制:只要数组中第一个 Promise 的状态发生改变(无论是 fulfilled 还是 rejected),Promise.race 的状态就会跟着改变,并返回那个最快的 Promise 的结果/错误。
  • 适用场景:网络请求超时处理。将一个真实的请求和一个定时器 Promise 放在一起,如果定时器先触发,就提示超时。

代码示例

javascript
const p1 = new Promise((resolve) => setTimeout(() => resolve('请求数据成功'), 500));
const p2 = new Promise((_, reject) => setTimeout(() => reject('请求超时'), 300)); // 这个更快

Promise.race([p1, p2])
  .then(res => console.log(res))
  .catch(err => console.log(err)); 
// 输出: '请求超时' (因为 300ms < 500ms,p2 先执行完)

3. Promise.allSettled() —— “无论结果如何,都要等到最后”

比喻:期末考试,无论学生考及格还是不及格,老师都要等所有人都交卷后,把所有人的成绩单收上来汇总。

  • (ES2020 引入)
  • 执行机制:等待数组中所有的 Promise 都执行完毕(无论成功还是失败)。
  • 成功返回值永远不会触发 reject。它会等待所有 Promise 执行结束后,返回一个数组,包含每一个 Promise 的结果对象。
    • 成功的对象格式:{ status: 'fulfilled', value: 结果值 }
    • 失败的对象格式:{ status: 'rejected', reason: 错误原因 }
  • 适用场景:多个互不依赖的请求并发执行,你希望知道每一个请求的结果,即使有些失败了,也不影响你处理其他成功的请求(例如:批量上传 3 张图片,1 张失败了,但你想知道哪两张成功了,哪一张失败了)。

代码示例

javascript
const p1 = Promise.resolve('成功 1');
const p2 = Promise.reject('失败 2');
const p3 = Promise.resolve('成功 3');

Promise.allSettled([p1, p2, p3]).then(res => console.log(res));
/* 输出:
[
  { status: 'fulfilled', value: '成功 1' },
  { status: 'rejected', reason: '失败 2' },
  { status: 'fulfilled', value: '成功 3' }
]
*/

💡 核心总结对照表

方法 核心逻辑 何时进入 then (成功) 何时进入 catch (失败) 返回值格式
Promise.all 全部成功才算赢 所有 Promise 都成功 只要有 1个 Promise 失败就立即报错 [结果1, 结果2...]
Promise.race 最快的说了算 第一个完成且是成功 第一个完成且是失败 最先完成的那个值或错误
Promise.allSettled 包容一切等结局 所有 Promise 都执行完毕(无论成败) 永远不报错(除非传入的不是可迭代对象) [{status, value/reason}, ...]

(补充扩展:ES2021 还引入了 Promise.any(),它的逻辑是“只要有一个成功就算成功”,只有全部失败才会报错,正好和 Promise.all 是相反的。)

00:00
00:00