Open FrankKai opened 5 years ago
event loop允许Node.js执行非阻塞的I/O操作-----尽管JS是单线程的-----它尽可能地通过把操作卸载到系统内核(kernel)。
因为大多数现代的内核(kernel)是多线程的,它们可以在后台处理多个操作。当其中之一完成后,kernel会告诉Node.js一个适当的callback可以被添加到poll queue(轮询队列)中并且执行。
在Node.js启动后,它会初始化event loop,处理提供的输入脚本(或者是落入REPL、或document未涉及)。输入脚本可以进行async API调用、定时器、或者调用process.nextTick()
,然后开始处理事件循环。
下面的算法展示了最简版的event loop执行顺序。
一个盒子代表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系统有轻微的区别。
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或者定时器,如果没有的话,会检查是否干净。
原文:https://nodejs.org/de/docs/guides/event-loop-timers-and-nexttick/