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

JavaScript中Promise.race()实现:forEach绑定特定Promise回调的疑问

理解Promise.race()实现中forEach的作用

这个问题问得非常好!让我们一步步拆解这段Promise.race()的实现代码,搞清楚它到底是怎么工作的。

首先先看你提到的实现代码:

const race = (...promises) => new Promise((res, rej) => { 
  promises.forEach(p => p.then(res).catch(rej)); 
});

核心原理:Promise的"单次决议"特性

首先要记住Promise最关键的规则之一:一个Promise只能被决议(resolve或reject)一次。一旦它从pending状态变成fulfilled(成功)或rejected(失败),状态就永久固定了,后续再调用resolve/reject函数都不会改变它的状态。

forEach循环的实际作用

forEach在这里并没有什么特殊的"绑定特定Promise"的魔法,它只是做了一件事:给所有传入的Promise都挂上监听回调:

  • 对每个传入的Promise p,我们告诉它:"如果你成功了,就调用外层新Promise的res函数;如果你失败了,就调用外层新Promise的rej函数"

谁先完成谁"抢占"决议权

当你调用race(p1, p2, p3)时:

  1. 外层先创建一个处于pending状态的新Promise
  2. forEach遍历p1、p2、p3,给每个都绑定好then(res)和catch(rej)的回调
  3. 接下来就是看哪个Promise先完成:
    • 假设p2是第一个完成的(不管是成功还是失败),它会立刻调用对应的res或rej,把外层Promise的状态固定下来
    • 剩下的p1和p3后续完成时,虽然也会调用res或rej,但外层Promise已经有了确定的状态,这些调用会被直接忽略

举个直观的例子:

// 100ms后成功的Promise
const fastSuccess = new Promise(res => setTimeout(() => res('我先完成!'), 100));
// 200ms后失败的Promise
const slowFail = new Promise((_, rej) => setTimeout(() => rej('我晚了一步'), 200));

race(fastSuccess, slowFail)
  .then(result => console.log('结果:', result))
  .catch(err => console.error('错误:', err));

// 最终输出:结果: 我先完成!
// slowFail的rej在200ms时会被调用,但外层Promise已经被fastSuccess决议为成功,所以无效

总结

这段代码的核心就是利用Promise的"单次决议"特性:forEach只是批量给所有传入的Promise绑定了触发外层决议的回调,第一个完成的Promise会先锁定外层Promise的状态,后续的所有回调都无法再改变这个状态——这就是Promise.race()"竞速"的本质:返回第一个完成(无论成功或失败)的Promise的结果。

内容的提问来源于stack exchange,提问作者GalAbra

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 10:10:18