我们都知道,Node Event loop分为六个阶段,每个阶段都有自己的作用。如图:
我的疑问是,为什么要分成六个阶段,这样做有什么样的好处?有没有哪个阶段是可以被干掉或者合并的?
我最近做了一个总结,然后被人问到了这个问题。确实不知道,网上也查不到相应的资料。只能来求助大神了
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 大神,能具体讲讲定义的问题吗
@hyj1991 是说event loop和不同的运行环境有关,而与语言无关是吗?就好像andriod和iOS有各自的Event loop实现,浏览器和Node也有各自的event loop实现
@Sperak 事件循环里没有任务一说。事件循环里会根据条件产生事件,然后处理事件。处理事件的过程中,会执行一些跟事件相关的任务。
不要像某老师一样,靠猜和蒙来入门。勇敢一点,就去把 uv_run() 函数看懂,看懂之后,你就知道你之前总结里的十有五六都是错的。