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

关于JavaScript中await推迟微任务至next tick的技术疑问

关于MDN中await“推迟至NEXT tick”描述的疑问解答

问题背景

根据MDN关于await的文档:

当代码中遇到await时(无论是在async函数还是模块中),被等待的表达式会执行,而所有依赖该表达式值的代码会被暂停并推入微任务队列。

async function foo(name) {
  console.log(name, "start");
  console.log(name, "middle");
  console.log(name, "end");
}

foo("First");
foo("Second");

// 输出:
// First start
// First middle
// First end
// Second start
// Second middle
// Second end

在这种情况下,两个async函数实际上是同步的,因为它们不包含任何await表达式,三条语句在同一个tick中执行。

上述内容易于理解,但以下描述存在疑问:

然而,一旦存在一个await,函数就会变成异步的,后续语句的执行会被推迟至NEXT tick。

async function foo(name) {
  console.log(name, "start");
  await console.log(name, "middle");
  console.log(name, "end");
}

foo("First");
foo("Second");

// 输出:
// First start
// First middle
// Second start
// Second middle
// First end
// Second end

疑问点:为何此处会描述为推迟至NEXT tick?按照事件循环机制,微任务应在当前tick中执行,而非下一个tick,这是否存在矛盾?


解答

这其实是MDN采用了简化表述,这里的“NEXT tick”和我们常说的“宏任务tick”不是同一个概念,本质上并不矛盾:

  1. 事件循环的tick划分:通常我们说的“当前tick”指的是一个宏任务的执行周期,包含同步代码执行+微任务队列清空。而MDN里的“NEXT tick”,实际指的是当前同步代码执行完毕后,微任务队列的执行阶段——相对于await之前的同步代码,后续代码确实是在“下一个执行批次”里运行,所以用“next tick”来简化描述这个异步阶段。

  2. 结合代码的执行流程:

    • 调用foo("First"),同步执行console.log("First start"),接着执行await后的console.log("First middle")(这部分是同步执行的),随后await会把后续的console.log("First end")包装成微任务,放入微任务队列。
    • 当前同步代码未结束,继续调用foo("Second"),同步执行console.log("Second start")和console.log("Second middle"),同样把console.log("Second end")放入微任务队列。
    • 当当前宏任务的同步代码全部执行完毕后,立即清空微任务队列,依次执行First end和Second end——这部分操作属于当前宏任务tick内的微任务阶段,并没有等到下一个宏任务tick。
  3. 结论:MDN的描述是为了更直观地说明await会让后续代码脱离同步执行流,进入异步执行阶段,这里的“NEXT tick”是对微任务执行阶段的简化称呼,和事件循环中“微任务在当前宏任务tick内执行”的机制并不冲突。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 07:15:27