Node.js事件循环中setTimeout与fs.readFile执行顺序疑问
Node.js事件循环:为什么fs.readFile回调先于setTimeout执行?
先看你的代码:
const fs = require("fs"); setTimeout(() => { console.log("timeout"); }, 1000); fs.readFile("read.txt", "utf8", (err, data) => { console.log(data); });
原因核心在于定时器到期时间和事件循环执行时机的关系:
同步代码执行阶段:
- 调用
setTimeout时,Node会标记这个回调需在1000ms后执行,但不会立刻将其放入待执行的timers队列,要等时间真正到期后,才会把回调移进队列。 - 调用
fs.readFile时,Node会把文件读取任务交给后台线程池处理,同步代码很快执行完毕,事件循环开始运转。
- 调用
事件循环第一轮检查:
- 首先进入Timers阶段:此时距离
setTimeout被调用还没到1000ms,定时器未到期,这个阶段没有可执行的回调,直接跳过。 - 接着进入I/O回调阶段:后台线程已经完成了小文件
read.txt的读取,对应的回调已被放入I/O队列,事件循环立刻执行这个回调,输出hello。
- 首先进入Timers阶段:此时距离
后续事件循环:
事件循环会反复遍历各个阶段,直到1000ms到期后,下一次进入Timers阶段时,才会发现setTimeout的回调已可执行,进而输出timeout。
简言之:读取小文件的耗时远小于1000ms,在定时器到期前,事件循环已经跑完多轮,并在I/O阶段执行了文件读取的回调。
内容的提问来源于stack exchange,提问作者Zglob
相关产品推荐
相关产品推荐

