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

Node.js中await fetch对事件循环的影响及行为差异解析

Node.js事件循环:await对同步/异步执行顺序的影响

问题背景

我正在研究Node.js中同步与异步函数的事件循环逻辑,按我的理解同步函数会先执行,之后才轮到异步函数。但在下面的示例中,控制台日志的执行顺序在移除fetchAPI前的await关键字后发生了明显变化,想搞懂背后的原因,我忽略了什么?


带await的代码示例

const experiment = async () =>{

    const num = 1

    setTimeout(()=>console.log("Hello from timeout"),0)
    console.log(num)

    const fetchAPI = await fetch("https://xxxxxxxxxxxx").then(x=>{
        console.log("Hello from API")    
        return x.json()
    })

    console.log(fetchAPI.id)
    
    console.log("String")

    Promise.resolve().then(()=>console.log("In promise"))

}

experiment()

输出结果:

1
Hello from timeout
Hello from API
139
String
In promise

移除await后的代码示例

移除await后,对应代码行变为:

const fetchAPI = fetch("https://xxxxxxxxxxxx").then(x=>{
    console.log("Hello from API")    
    return x.json()
})

输出结果:

1
undefined
String
In promise
Hello from timeout
Hello from API

核心原因解析

带await时的执行逻辑

  • await的核心作用是暂停当前async函数的执行,直到后续的Promise状态变为resolved,才会恢复函数执行。
  • 执行到await fetch(...)时,experiment函数暂停,线程交还给事件循环。此时事件循环会先处理已进入队列的宏任务:setTimeout的回调属于宏任务,优先执行,输出Hello from timeout。
  • 当fetch请求完成、Promise状态变为resolved后,experiment恢复执行:先触发.then里的console.log("Hello from API"),接着把x.json()的结果赋值给fetchAPI,然后依次执行后续同步代码——输出fetchAPI.id(即返回的随机数139)、String,最后Promise.resolve().then(...)属于微任务,会在当前宏任务结束前执行,输出In promise。

移除await后的执行逻辑

  • 去掉await后,fetch(...)只是创建了一个处于Pending状态的Promise,但不会暂停experiment函数的执行,代码会一路同步跑完:
    1. 先输出1;
    2. 此时fetchAPI是一个未完成的Promise对象,打印fetchAPI.id自然得到undefined;
    3. 接着输出String;
    4. Promise.resolve().then(...)作为微任务,会被加入微任务队列,在当前同步代码执行完毕后立即执行,输出In promise。
  • 等当前宏任务(experiment函数的同步执行流程)全部完成后,事件循环才会处理宏任务队列:先执行setTimeout的回调(输出Hello from timeout),之后fetch请求完成,其.then回调作为微任务执行,输出Hello from API。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 19:52:38