You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Promise.race()返回已兑现Promise而非首个已拒绝Promise的原因咨询

Promise.race()返回已兑现Promise而非首个已拒绝Promise的原因咨询

我完全懂你的疑惑!按照MDN对Promise.race()的描述,它应该返回第一个完成状态变更(不管是兑现还是拒绝)的Promise结果,但你的代码里明明把promise2放在了Promise.race的数组首位,且三个Promise都是2秒后触发状态变更,结果却输出了Promise 1,这确实有点反直觉。

问题的核心出在**setTimeout的延迟特性**以及JavaScript事件循环的任务调度逻辑上:

  • 首先,setTimeout的延迟时间是「最小等待时间」,不是精确的到期时间。当多个定时器设置了完全相同的延迟值时,它们的回调函数会被批量加入到宏任务队列中,但JavaScript引擎处理这些回调的顺序并不是严格按照Promise的创建顺序来的——这取决于引擎内部的调度机制,属于不确定的行为。
  • 在你的代码运行实例中,promise1的resolve回调恰好比promise2的reject回调先被引擎执行了,所以Promise.race()就捕获到了这个最先完成的兑现状态,输出了Promise 1。如果换一次运行环境或者重新执行几次,你可能会得到Error Promise 2或者Error Promise 3的结果,因为这三个Promise的状态变更时间几乎完全同步,谁先被处理是随机的。

你可以做个小测试验证这个逻辑:把promise2的setTimeout延迟改成1999毫秒(比另外两个少1毫秒),这时候它的状态变更一定会先触发,Promise.race()就会进入catch块,输出Error Promise 2了。

再补充下MDN那段描述的关键点:它说的「第一个settle的Promise」是指实际最先完成状态切换的那个,而当多个Promise的settle时间完全重合时,这个顺序是不可预测的,不能依赖数组的顺序来判断谁先被处理。

附你的测试代码:

try{
  // Promise 1
  const promise1 = new Promise((resolve, reject) => {
    setTimeout(() => resolve('Promise 1'), 2000);
  });

  // Promise 2
  const promise2 = new Promise((resolve, reject) => {
    setTimeout(() => reject('Error Promise 2'), 2000);
  });

  // Promise 3
  const promise3 = new Promise((resolve, reject) => {
    setTimeout(() => reject('Error Promise 3'), 2000);
  });

  const result = await Promise.race( [promise2, promise1, promise3]);
  console.log(result);
} catch(err) {
  console.log(err.message);
}

输出结果:

Promise 1

备注:内容来源于stack exchange,提问作者thundrstorm

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.20 09:44:36