自行实现的Promise.race()返回结果不符合预期,是什么原因导致的?
Promise.race自定义实现异常原因分析
问题根因
核心问题出在你对promise回调的绑定方式:你当前使用p.then(resolve).catch(reject)的写法,导致reject回调的触发时机晚于同队列中其他已resolve状态promise的resolve回调。
p.then(resolve).catch(reject)等价于p.then(resolve, undefined).then(undefined, reject),本质是两级promise链式调用:
- 当输入的p是rejected状态时,第一个
then没有传入onRejected处理函数,会直接返回一个新的rejected状态的promise- 你绑定的
reject回调实际是挂载在这个新返回的promise上,而非原始的p上- 这就导致rejected状态的p的回调入队顺序,比直接在p上绑定onRejected要晚一个微任务周期
在你的测试用例中:
- 第一个
Promise.reject('test_error')的reject回调要等到第二级promise的微任务才会执行 - 第二个
Promise.resolve('test_value')的resolve回调直接挂载在原始promise上,会在第一级微任务就执行
因此会先触发resolve('test_value'),而Promise状态一旦敲定就不会再变更,最终你得到的是不符合预期的test_value。
修复方案
把回调绑定方式修改为直接给then传入两个参数,同时绑定onFulfilled和onRejected回调,确保两个回调都挂载在原始promise上,执行顺序和promise状态变更顺序一致:
const promiseRace = promises => new Promise((resolve, reject) => { promises.forEach(p => { if ( typeof p === 'object' && 'then' in p && typeof p.then === 'function' ) { // 直接给then传两个参数,不要链式调用catch p.then(resolve, reject); } else { resolve(p); } }); });
修改后测试promiseRace([Promise.reject('test_error'), Promise.resolve('test_value')])会正确返回test_error,符合预期。
内容的提问来源于stack exchange,提问作者BERTOLDO
相关产品推荐
相关产品推荐

