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

为何调用栈空闲时异步代码仍未执行?JS异步机制疑问

JavaScript异步执行的核心:宏任务与微任务

你遗漏了JavaScript事件循环中微任务和宏任务的优先级差异,以及同步代码执行的绝对优先级。我们一步步拆解代码执行流程,就能明白输出顺序的原因:

先明确两个关键概念

  • 同步代码:直接进入调用栈按顺序执行,执行完之前不会处理任何异步任务。
  • 异步任务分两类:
    • 微任务:优先级高,包含Promise的then/catch/finally、MutationObserver等。
    • 宏任务:优先级低,包含setTimeout、setInterval、DOM事件、AJAX请求等。

代码执行全流程

  1. 执行console.log('test start');,输出test start(你的实际输出可能遗漏了这行,但代码逻辑中存在)。
  2. 调用setTimeout(...):作为宏任务,回调函数被放入宏任务队列等待后续处理。
  3. 调用Promise.resolve(...).then(...):Promise的then回调是微任务,被放入微任务队列。
  4. 执行两次fu():属于同步代码,直接进入调用栈执行,输出两次after 1,执行完后回到全局代码。
  5. 执行console.log('Test End');:仍是同步代码,输出Test End,此时全局同步代码全部执行完毕,调用栈为空。

你标记的位置处于两次fu()之后、console.log('Test End');之前,此时调用栈并未完全清空——全局代码还剩最后一行未执行,所以异步任务根本没到执行时机。

异步任务的执行时机

当调用栈彻底清空后,事件循环会遵循以下顺序处理异步任务:

  1. 先清空所有微任务队列:取出Promise回调执行,输出Resolve promise1。
  2. 微任务队列处理完毕后,再处理宏任务队列:取出setTimeout回调执行,输出0 sec timer。

核心规则总结

  • 同步代码永远优先执行,必须等当前调用栈内所有同步代码执行完毕,才会处理异步任务。
  • 异步任务中微任务优先级高于宏任务,必须等所有微任务执行完毕,才会开始执行宏任务。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 09:18:13