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

microtask queue指令优先级是否高于根级指令?JS异步顺序疑问

核心原因

你的推断错误源于对async函数执行机制的常见误解:调用async函数时,函数体从开头到第一个await/return/抛出错误位置的所有代码,都是同步执行的,并不会把整个函数直接丢进微任务队列。

逐行拆解你这段代码的执行流程

  • 首先执行最外层的run():
    1. 同步打印calling async func,碰到await func(),此时暂停run的执行,把await后面的console.log('done')注册为微任务,转去同步执行func()。
  • 进入func执行:
    2. 因为是async函数,开头没有await,所以同步打印async func called,接下来执行anotherAsync()调用,和调用普通同步函数没有区别,直接进入anotherAsync内部执行。
  • 进入anotherAsync执行:
    3. 这个async函数内部全程没有await,所以整个函数体全部同步跑完:先打印Another async called,执行完10w次的空循环,再打印Another async finished,最后返回一个状态为fulfilled的Promise,退出函数回到func的调用位置。
  • 回到func继续执行:
    4. 由于你调用anotherAsync()时没有加await,引擎不会等待它返回的Promise,直接往下同步执行,打印async func finished。此时func执行完毕,返回的Promise状态为fulfilled,之前await func()挂起的微任务进入队列。
  • 当前调用栈清空,开始执行微任务队列:
    5. 执行之前挂起的run后续代码,打印done,流程结束。

对你的猜想的纠正

不存在“await外层func会隐式await内部未加await的anotherAsync”的规则,引擎也不会特殊优先处理同作用域指令,你看到的顺序纯粹是因为async函数开头的代码是同步执行的。
你可以做个验证:给anotherAsync加一行await,代码如下:

const anotherAsync = async () => {
  console.log('Another async called');
  await Promise.resolve(); // 新增这行,触发微任务分割
  for (let i=0; i<=100000; i++) {

  }
  console.log('Another async finished');
};

此时运行结果就会变成:

calling async func
async func called
Another async called
async func finished
done
Another async finished

这时候anotherAsync执行到新增的await位置时,会把await后面的所有代码注册为微任务,先跳出函数回到func继续执行后续逻辑,等调用栈空、前面的微任务(打印done)执行完之后,才会回来跑anotherAsync剩下的代码。

记住一个简单判断规则:只有async函数中await后面的代码、以及async函数返回后挂载的then/catch/finally回调才会进入微任务队列,函数开头到第一个await之前的逻辑,永远是调用时同步执行的。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 01:09:24