阅读 43

EventLoop

1. EventLoop

EventLoop是一个程序结构,用于等待和发送消息和事件。简单说,就是在程序中设置两个线程:一个负责程序本身的运行,称为"主线程";另一个负责主线程与其他进程(主要是各种I/O操作)的通信,被称为"Event Loop线程"(可以译为"消息线程")。

大体解释一下NodeJS的Event Loop过程:

  1. 执行全局Script的同步代码
  2. 执行microtask微任务,先执行所有Next Tick Queue中的所有任务,再执行Other Microtask Queue中的所有任务
  3. 开始执行macrotask宏任务,共6个阶段,从第1个阶段开始执行相应每一个阶段macrotask中的所有任务,注意,这里是所有每个阶段宏任务队列的所有任务,在浏览器的Event Loop中是只取宏队列的第一个任务出来执行,每一个阶段的macrotask任务执行完毕后,开始执行微任务,也就是步骤2

1.1 宏队列

宏队列,macrotask,也叫tasks。 一些异步任务的回调会依次进入macro task queue,等待后续被调用,这些异步任务包括:

  1. setTimeout
  2. setInterval
  3. setImmediate (Node独有)
  4. requestAnimationFrame (浏览器独有)
  5. I/O
  6. UI rendering (浏览器独有)

NodeJS的Event Loop中,执行宏队列的回调任务有6个阶段,如下图:

image.png

各个阶段执行的任务如下:

  1. timers阶段:这个阶段执行setTimeout和setInterval预定的callback
  2. I/O callback阶段:执行除了close事件的callbacks、被timers设定的callbacks、setImmediate()设定的callbacks这些之外的callbacks
  3. idle, prepare阶段:仅node内部使用
  4. poll阶段:获取新的I/O事件,适当的条件下node将阻塞在这里
  5. check阶段:执行setImmediate()设定的callbacks
  6. close callbacks阶段:执行socket.on('close', ....)这些callbacks

NodeJS中宏队列主要有4个

  1. Timers Queue
  2. IO Callbacks Queue
  3. Check Queue
  4. Close Callbacks Queue

这4个都属于宏队列,但是在浏览器中,可以认为只有一个宏队列,所有的macrotask都会被加到这一个宏队列中,但是在NodeJS中,不同的macrotask会被放置在不同的宏队列中。

1.2 微队列

微队列,microtask,也叫jobs。 另一些异步任务的回调会依次进入micro task queue,等待后续被调用,这些异步任务包括:

  1. process.nextTick (Node独有)
  2. Promise
  3. Object.observe
  4. MutationObserver

NodeJS中微队列主要有2个:

  1. Next Tick Queue:是放置process.nextTick(callback)的回调任务的
  2. Other Micro Queue:放置其他microtask,比如Promise等

在浏览器中,也可以认为只有一个微队列,所有的microtask都会被加到这一个微队列中,但是在NodeJS中,不同的microtask会被放置在不同的微队列中。

1.3 举例

console.log('script start');

setTimeout(function() {
  console.log('setTimeout');
}, 0);

Promise.resolve(
    console.log('Promise')
).then(function() {
  console.log('promise1');
}).then(function() {
  console.log('promise2');
});
console.log('script end');
复制代码
输出结果:
script start
Promise
script end
promise1
promise2
setTimeout
复制代码
文章分类
前端
文章标签