浅析 Node.js Event Loop

介绍

要了解浏览器的事件循环,我们首先要掌握 javascript 是单线程,所有的任务都是在一条线程上面去执行,只有等上一个任务执行好了才会继续执行下一个任务。然后我们需要了解任务的概念,javaScript 可以分为两种任务,同步任务和异步任务,同步任务会在主线程上面执行,形成一条执行栈。异步任务会在主线程之外的任务队列中执行,每当异步任务支持完成之后,就会在任务队列里面插入一个事件。上面我们说到了任务栈和任务队列,我们需要掌握栈和队列的基本区别,栈是由系统分配内存,栈的特点是先进后出,而队列的特点是先进先出。了解了栈和队列之后,我们需要了解宏任务和微任务,什么是宏任务呢?比如 setTimeout, setInterval,setImmediate 这些都属于宏任务;什么是微任务呢?微任务是指进行系统 I/O 操作的一些事件,比如说 Process.nextTick, Promise.then 这些属于微任务。浏览器是如何运行的呢,首先会执行栈里面的同步代码,比如说正常的变成复制,循环,方法或者类的实例化,然后会优先执行微任务,最后才会执行宏任务。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
setTimeout(function(){
console.log(4)
},0);
new Promise(function(resolve){
console.log(1)
for( var i=0 ; i<10000 ; i++ ) {
i==9999 && resolve()
}
console.log(2)
})
.then(function(){
console.log(5)
});
console.log(3);

1,2,3,5,4

Node.js 中的 Event loop

我们写的 Javascript 代码首先交给 V8 引擎去处理
代码中调用 Node API
Node 会交给 Libuv 去处理,通过阻塞 I/O和多线程实现了异步 I/O
通过事件驱动的形式放置在事件队列中去,最终交付给我们的应用
执行顺序如下:首先会执行主线程中的同步任务,然后寻找是否存在微任务,如果存在则执行微任务,不存在则寻找 timers 中的宏任务放入至事件队列,如果后面存在微任务不执行,继续寻找是否存在宏任务,一次全部执行完宏任务之后,然后再执行微任务。