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

耗时相同的任务在Promise.race与Promise.all中是否可能后提交的先完成?

问题解答

1. Promise.race示例为何始终输出1,是否有可能输出2

你调用promises.push(test(1))时,会立即执行test(1)内部逻辑:

  • 调用sleep(1000),注册第一个延迟1000ms的setTimeout回调
    随后调用promises.push(test(2)),执行test(2)内部逻辑:
  • 调用sleep(1000),注册第二个延迟1000ms的setTimeout回调

JS的事件循环机制中,同类型、同延迟的定时器回调会按照注册顺序加入宏任务队列,队列遵循先进先出的执行规则。
所以1000ms后,test(1)的定时器回调会先执行,先resolve对应的Promise,Promise.race会直接采用第一个完成的Promise结果,因此始终输出1。
极端场景下可能输出2:如果运行环境的定时器存在精度误差、或者系统调度导致第一个定时器的回调被意外延迟(比如主线程刚好被其他高优先级任务占满1000ms的时间节点),才可能出现第二个定时器先触发的情况,但这种情况在常规运行环境中出现概率极低。

2. 耗时相同的异步任务是否保证先提交先完成

JS不会对所有异步任务做「先提交先完成」的保证,分场景判断:

  • 同类型、触发时机完全一致的异步任务(比如同延迟的setTimeout、同批次的微任务),会按队列先进先出规则,先提交的先执行
  • 不同类型的异步任务(比如宏任务和微任务),即使微任务后提交,也会比当前宏任务后续的其他宏任务先执行
  • 耗时不确定的异步任务(比如网络请求、文件IO),即使先提交,也可能因为下游响应慢,反而后完成

3. 为何a++的示例始终输出100,是否存在线程上下文切换

首先纠正一个误区:你写的这段代码不属于多线程代码。JavaScript默认是单线程执行的,除非主动开启Web Worker(浏览器)或者worker_threads(Node.js),否则所有代码都在主线程运行,不存在多线程上下文切换,也不存在抢占式执行,同一时间只会有一段代码在执行,因此不会出现多线程场景下的竞态条件。
另外你的test1函数没有任何await语句,async函数中碰到第一个await之前的代码都是同步执行的:你循环调用test1()的过程中,a++会直接同步执行,100次循环跑完的时候a已经变成100了,push到数组里的都是已经resolve的Promise,后续Promise.all只是等待所有已完成的Promise结束而已,自然输出100。
就算你给test1加上await Promise.resolve(),a++会被推入微任务队列,微任务队列也是按顺序执行,不会出现两个a++同时执行的情况,最终结果仍然是100。


内容的提问来源于stack exchange,提问作者K. Zhu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 15:24:01