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)时:
- 外层先创建一个处于
pending状态的新Promise - forEach遍历p1、p2、p3,给每个都绑定好
then(res)和catch(rej)的回调 - 接下来就是看哪个Promise先完成:
- 假设p2是第一个完成的(不管是成功还是失败),它会立刻调用对应的
res或rej,把外层Promise的状态固定下来 - 剩下的p1和p3后续完成时,虽然也会调用
res或rej,但外层Promise已经有了确定的状态,这些调用会被直接忽略
- 假设p2是第一个完成的(不管是成功还是失败),它会立刻调用对应的
举个直观的例子:
// 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
相关产品推荐
相关产品推荐

