JavaScript Promise.race无法同步resolve?如何修改代码输出two?
问题描述
MDN提供了Promise.race的示例,但该示例因无依赖竞态结果的代码存在一定误导性。我对代码调整后出现异常行为:运行下方代码时,最后一行console.log输出的是'zero'。我原本以为调用Promise.race的then方法会使执行同步,但实际并非如此。请问需要修改哪里才能让最后一行日志输出'two'?
const promise1 = new Promise((resolve, reject) => { setTimeout(resolve, 500, 'one'); }); const promise2 = new Promise((resolve, reject) => { setTimeout(resolve, 100, 'two'); }); (async () => { let val = 'zero'; Promise.race([promise1, promise2]).then((result) => { val = result; console.log("Assigned value", val); }) console.log(val); })();
解决方案
问题出在异步代码的执行顺序上:Promise.race()是异步操作,它的then回调会被放入微任务队列,要等当前同步代码全部执行完才会运行。而最后一行的console.log(val)是同步代码,会在then回调执行前就运行,所以此时val还是初始值'zero'。
要让最后一行输出'two',有两种简单的修改方式:
方式一:用await等待异步结果
既然已经在async函数中,直接用await获取Promise.race的结果,这样代码会暂停等待Promise完成,再执行后续逻辑:
const promise1 = new Promise((resolve, reject) => { setTimeout(resolve, 500, 'one'); }); const promise2 = new Promise((resolve, reject) => { setTimeout(resolve, 100, 'two'); }); (async () => { let val = 'zero'; // 等待Promise.race完成,拿到结果后再赋值 val = await Promise.race([promise1, promise2]); console.log("Assigned value", val); console.log(val); // 此时val已更新为'two' })();
方式二:将console.log移入then回调
如果不想用await,就把依赖异步结果的代码放在then的回调内部,确保它在Promise完成、val被更新后再执行:
const promise1 = new Promise((resolve, reject) => { setTimeout(resolve, 500, 'one'); }); const promise2 = new Promise((resolve, reject) => { setTimeout(resolve, 100, 'two'); }); (async () => { let val = 'zero'; Promise.race([promise1, promise2]).then((result) => { val = result; console.log("Assigned value", val); console.log(val); // 移入回调,保证在赋值后执行 }) })();
核心逻辑是:异步操作不会阻塞同步代码的执行,必须通过等待(await)或者把后续逻辑绑定到异步回调中,才能确保拿到更新后的值。
内容的提问来源于stack exchange,提问作者Andi Abrudan
相关产品推荐
相关产品推荐

