关于Promise.race()自定义实现的疑惑求助
先看这段自定义Promise.race()的实现代码:
const race = function(promisesArray) { return new Promise((resolve, reject) => { promisesArray.forEach((innerPromise) => { Promise.resolve(innerPromise) .then(resolve, reject) .catch(reject); }); }); };
疑问1解答
你提到的**"Promise.resolve(innerPromise)总会返回以innerPromise为值的已决议Promise"**这个表述是错误的。
Promise.resolve()的行为分两种情况:
- 如果传入的
innerPromise本身就是一个Promise实例,Promise.resolve()会直接继承这个Promise的状态——它不会把这个Promise包装成新的已决议Promise,而是直接返回和原Promise状态一致的Promise。也就是说,原Promise是pending,它就还是pending;原Promise是rejected,它也会是rejected。 - 只有当传入的是普通值(非Promise类型)时,
Promise.resolve()才会返回一个以该值为结果的fulfilled状态Promise。
所以它并不是"总会返回以innerPromise为值的已决议Promise",自然也不会"总会进入.then块的第一个回调"。
疑问2解答
.then(resolve, reject)里的两个参数是状态触发的回调:第一个回调会在Promise.resolve(innerPromise)变成fulfilled状态时被调用,第二个回调会在它变成rejected状态时被调用。
之所以不是总是调用第一个回调,核心原因就是上面说的——Promise.resolve(innerPromise)的状态完全由传入的innerPromise决定:
- 如果
innerPromise最终是fulfilled,那Promise.resolve(innerPromise)也会是fulfilled,这时候触发第一个回调(外层的resolve),把外层Promise的状态设为fulfilled。 - 如果
innerPromise最终是rejected,那Promise.resolve(innerPromise)也会是rejected,这时候触发第二个回调(外层的reject),把外层Promise的状态设为rejected。
后面的.catch(reject)是兜底处理resolve或reject本身可能抛出的异常(虽然这种情况极少发生),确保外层Promise能捕获到所有可能的错误。
补充下这段代码的核心逻辑:Promise.race()的本质就是谁先完成状态决议(不管成功还是失败),就把外层Promise的状态同步成它的状态。这段代码遍历所有传入的Promise,给每个Promise绑定回调,只要有一个Promise先完成状态变更,就立刻调用外层的resolve或reject,而Promise一旦决议就不会再改变状态,所以后续的Promise回调不会影响最终结果。
内容的提问来源于stack exchange,提问作者Varun

