FrankKai / FrankKai.github.io

FE blog
https://frankkai.github.io/
363 stars 39 forks source link

[译]Node.js Event Loop, Timers 和 process.nextTick() #145

Open FrankKai opened 5 years ago

FrankKai commented 5 years ago

原文:https://nodejs.org/de/docs/guides/event-loop-timers-and-nexttick/

FrankKai commented 5 years ago

什么是Event Loop?

event loop允许Node.js执行非阻塞的I/O操作-----尽管JS是单线程的-----它尽可能地通过把操作卸载到系统内核(kernel)。

因为大多数现代的内核(kernel)是多线程的,它们可以在后台处理多个操作。当其中之一完成后,kernel会告诉Node.js一个适当的callback可以被添加到poll queue(轮询队列)中并且执行。

FrankKai commented 5 years ago

Event Loop原理

在Node.js启动后,它会初始化event loop,处理提供的输入脚本(或者是落入REPL、或document未涉及)。输入脚本可以进行async API调用、定时器、或者调用process.nextTick(),然后开始处理事件循环。 下面的算法展示了最简版的event loop执行顺序。 image 一个盒子代表event loop的一个阶段。

FIFOqueue maximum number 每一个阶段都有一个FIFO的callback queue执行。但是每个阶段的队列都有自己的特点,当event loop进入到一个给定的阶段后,它可以执行那个阶段中的任何操作,然后执行阶段队列中的callback,知道队列耗尽或者达到callback执行最大数(maximum number)。当queue的被耗尽或者callback限制达到最大时,event loop将会移动到下一个阶段。

这些操作可能去调度很多的操作,poll阶段的新events处理会被kernel队列处理,poll events可以在polling事件处理时进入队列。结果就是,耗时长的callback允许轮询阶段的运行时间比Timers的阀值时间长。

对于windows、linux系统有轻微的区别。

FrankKai commented 5 years ago

event loop各阶段对比

phase 阶段 作用
timers 计时器 这个阶段会执行setTimeout和setInterval的callback
pending callbacks pending的callback 执行延迟到下一个loop遍历的I/O回调
idle,prepare 空闲的,预备的 仅在内部使用
poll 轮询,带了数据的连接 查询新的I/O事件;执行I/O相关的回调(除了近距离回调的所有,timers的回调,以及setImmediate)node会在适当时阻塞这里
check 检查 这里执行setImmediate回调
close callbacks 关闭callback 一些关闭callback,例如socket.on('close', ...)

每次event loop,node都会检查有没有async的I/O或者定时器,如果没有的话,会检查是否干净。