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

为什么自定义async函数会阻塞?JS异步代码执行逻辑疑问

问题1:为什么初始版本的sleep没有异步执行,第二个调用要等第一个完成?

async 函数仅对函数内 await 之后的代码做异步调度,await 之前的所有代码都是同步阻塞执行的。你写的初始版本 sleep 没有用到任何 await 关键字,整个 while 死循环都是同步代码,调用时会直接卡住JS主线程,直到循环结束才会返回一个已完成状态的Promise。
执行流程实际为:

  • 调用第一个 sleep(5000),主线程卡死5秒跑循环,返回已完成的Promise
  • 执行第一个 console.log,此时距离start已经过了5秒
  • 调用第二个 sleep(5000),主线程再卡死5秒跑循环,返回已完成的Promise
  • 执行第二个 console.log,此时距离start已经过了10秒左右

问题2:为什么1!打印早于2!

then 回调会在所属Promise进入已完成状态后,被加入微任务队列等待执行。第一个sleep的循环先跑完,Promise先进入已完成状态,对应的then回调先进入微任务队列;第二个sleep的循环后跑完,Promise后进入已完成状态,对应的then回调后进入微任务队列。主线程的所有同步代码跑完后,会按顺序执行微任务队列的回调,所以先打印1!再打印2!。

问题3:把sleep替换为无timeout的耗时计算逻辑会得到什么结果?

如果你的耗时计算逻辑依然是跑在JS主线程的同步代码,不管你包装成async函数还是普通函数返回Promise,只要没有把计算逻辑交给Worker线程/其他异步API处理,都会和初始版本的死循环sleep表现完全一致:

  • 两次sleep调用分别阻塞主线程对应计算时长
  • 两个console.log分别打印两次计算累加的时长数值
  • 最后按顺序打印1!、2!

原因是JS是单线程事件循环模型,所有同步计算任务都会占用主线程,只有定时器、IO、Worker这类运行时提供的异步API,才会把任务交给其他线程处理,不阻塞主执行栈的代码运行。

内容的提问来源于stack exchange,提问作者iacgm

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 14:15:08