Node Event loop为什么要分成六个阶段,这样做和浏览器的实现原理相比有什么样的好处?
发布于 6 年前 作者 Sperak 4622 次浏览 来自 问答

我们都知道,Node Event loop分为六个阶段,每个阶段都有自己的作用。如图: loop2.png

我的疑问是,为什么要分成六个阶段,这样做有什么样的好处?有没有哪个阶段是可以被干掉或者合并的?

我最近做了一个总结,然后被人问到了这个问题。确实不知道,网上也查不到相应的资料。只能来求助大神了

10 回复

Event loop:即事件循环,是JavaScript引擎处理异步任务的方式。

开篇就是错的。

时间循环的精髓就是 循环 和 事件。只要有循环,循环中能产生事件,就可以视作是事件循环的一种实现。这跟他内部是分为几个阶段是完全无关的,内部的几个阶段的区分完全是为了处理不同类的事件而决定的,在 libuv/Node 中,需求上就是有这么几种。

https://cnodejs.org/topic/5a9108d78d6e16e56bb80882

@youth7 的文章把各个阶段的作用都讲得很明白,仔细阅读下就会有收获的。

分阶段实现一方面让有相同关注点的逻辑聚合在一起,另一方面也使逻辑更加清晰,代码更加清晰。如果你自己设计,迭代几次后也会越来越趋向于这种结果的。

timers阶段相当于libuv自己提供的api,在不断的loop中可以注册触发回调。
IO callbacks相当于运行io的callback,也就是stream流式传输的回调,比如我用libuv中提供的流读文件,或者IPC之类的。
而idle是为了越过poll直接执行check的,所以idle必须在前面。
而prepare则类似于poll之前的缓冲,因为poll会阻塞,idle又可以越过poll,所以可以单独在prepare阶段特殊处理,嵌入特定idle。
poll阶段为什么放到后边,因为有uv_stop的存在,你可以用uv_stop来关闭事件循环,而这个开关是放在prepare和poll之间的,也就是如果我在poll之后stop了,libuv还会跑一次循环直到跑完prepare,这样正好保证了IO callbacks的完整退出。
check和close感觉就没必要介绍了。
还有,你最好先缕清libuv和v8以及node之间的关系,再进行钻研。。。你的总结看了定义的第一句就感觉没必要继续读下去了。

运行下如下代码就知道为撒了,另外请参考http://www.ruanyifeng.com/blog/2018/02/node-event-loop.html

const util = require(‘util’); const readFile = util.promisify(require(‘fs’).readFile);

const fs = require(‘fs’);

function someAsyncOperation (callback) { // Assume this takes 95ms to complete console.log(同步任务 9, 此时发出异步请求); fs.readFile(’/path/to/file’, callback); }

const timeoutScheduled = Date.now();

setTimeout(() => { const delay = Date.now() - timeoutScheduled; console.log(Timer , ${delay}ms have passed since I was scheduled); });

setTimeout(() => console.log(Timer , 次轮 1)); setImmediate(() => console.log(Timer, 次轮 2));

Promise.resolve().then(() => console.log(microTaskQueue 3)); process.nextTick(() => console.log(nextTickQueue 4)); process.nextTick(() => console.log(nextTickQueue 5)); Promise.resolve().then(() => console.log(microTaskQueue 6));

Promise.resolve().then(() => { console.log(microTaskQueue 7); });

someAsyncOperation(() => { console.log(poll , I/O callback 10); const startCallback = Date.now(); });

console.log(同步任务8);

@JacksonTian 任务队列中都是异步任务,主进程通过Event Loop来加载任务。把Event Loop称为异步任务的方式有什么问题吗……是不是我这种说法太狭隘了?

@xtx1130 大神,能具体讲讲定义的问题吗

@Sperak event loop 和 js 引擎没有关系

来自酷炫的 CNodeMD

@hyj1991 是说event loop和不同的运行环境有关,而与语言无关是吗?就好像andriod和iOS有各自的Event loop实现,浏览器和Node也有各自的event loop实现

@Sperak 事件循环里没有任务一说。事件循环里会根据条件产生事件,然后处理事件。处理事件的过程中,会执行一些跟事件相关的任务。

不要像某老师一样,靠猜和蒙来入门。勇敢一点,就去把 uv_run() 函数看懂,看懂之后,你就知道你之前总结里的十有五六都是错的。

回到顶部