Node.js系列六 - 深入事件循环

2021-02-06  本文已影响0人  懂会悟

1、 Node的事件循环

1.1. Node的事件循环

浏览器中的EventLoop是根据HTML5定义的规范来实现的,不同的浏览器可能会有不同的实现,而Node中是由libuv实现的。

libuv到底是什么呢?

1.2. 阻塞IO和非阻塞IO

如果我们希望在程序中对一个文件进行操作,那么我们就需要打开这个文件:通过文件描述符。

操作系统为我们提供了 阻塞式 调用和 非阻塞式 调用:

所以我们开发中的很多耗时操作,都可以基于这样的 非阻塞式 调用:

但是非阻塞IO也会存在一定的问题:我们并没有获取到需要读取(我们以读取为例)的结果

那么这个轮训的工作由谁来完成呢?

libuv提供了一个线程池(Thread Pool):

阻塞和非阻塞,同步和异步有什么区别?

1.3. Node事件循环的阶段

我们最前面就强调过,事件循环像是一个桥梁,是连接着应用程序的JavaScript和系统调用之间的通道:

但是一次完整的事件循环Tick分成很多个阶段:

我们会发现从一次事件循环的Tick来说,Node的事件循环更复杂,它也分为微任务和宏任务:

但是,Node中的事件循环不只是 微任务队列和 宏任务队列:

所以,在每一次事件循环的tick中,会按照如下顺序来执行代码:

1.4. 实操

async function async1() {
  console.log('async1 start')
  await async2()
  console.log('async1 end')
}

async function async2() {
  console.log('async2')
}

console.log('script start')

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

setTimeout(function () {
  console.log('setTimeout2')
}, 300)

setImmediate(() => console.log('setImmediate'));

process.nextTick(() => console.log('nextTick1'));

async1();

process.nextTick(() => console.log('nextTick2'));

new Promise(function (resolve) {
  console.log('promise1')
  resolve();
  console.log('promise2')
}).then(function () {
  console.log('promise3')
})

console.log('script end')
//  result
script start
async1 start
async2
promise1
promise2
script end
nextTick
async1 end
promise3

setTimeout0
setImmediate
setTimeout2
上一篇下一篇

猜你喜欢

热点阅读