浅谈Node.js的事件环(event loop)

栏目: Node.js · 发布时间: 6年前

内容简介:nodejs 具有事件驱动和非阻塞但线程的特点,使相关应用变得比较轻量和高效。当应用程序需要相关I/O操作时,线程并不会阻塞,而是把I/O操作移交给底层类库(如:libuv)。此时nodejs线程会去处理其他的任务,当底层库处理完相关的I/O操作后,会将主动权再次交还给nodejs线程。因此event loop的作用就是起到调度线程的作用,如当底层类库处理I/O操作后调度nodejs单线程处理后续的工作。也就是说当nodejs 程序启动的时候,它会开启一个event loop以实现异步的api调度、sch

nodejs 具有事件驱动和非阻塞但线程的特点,使相关应用变得比较轻量和高效。当应用程序需要相关I/O操作时,线程并不会阻塞,而是把I/O操作移交给底层类库(如:libuv)。此时nodejs线程会去处理其他的任务,当底层库处理完相关的I/O操作后,会将主动权再次交还给nodejs线程。因此event loop的作用就是起到调度线程的作用,如当底层类库处理I/O操作后调度nodejs单线程处理后续的工作。也就是说当nodejs 程序启动的时候,它会开启一个event loop以实现异步的api调度、schedule timers 、回调process.nextTick()。

从上也可以看出nodejs 虽说是单线程,但是在底层类库处理异步操作的时候仍然是多线程。

2.引出问题

在node环境中我们运行如下代码,会出现怎么样的执行结果?

let fs = require('fs');
setTimeout(function(){
    Promise.resolve().then(()=>{
        console.log('then2');
    })
},0);
Promise.resolve().then(()=>{
    console.log('then1');
});
fs.readFile('./gitigore',function(){
    process.nextTick(function(){
        console.log('nextTick')
    })
    setImmediate(()=>{
        console.log('setImmediate')
    });
});
复制代码

在node环境的执行结果是

then1
then2
nextTick
setImmediate
复制代码

3.开始事件循环之前,nodejs初始化

产出这样的结果,来源于Node.js对事件的循环操作顺序。在Node.js的官方文档中,对初始化event loop有这样的描述 The Node.js Event Loop, Timers, and process.nextTick()

浅谈Node.js的事件环(event loop)

-当Node.js启动的时候,他会初始化Event Loop,处理提供的输入脚本,这可能会使异步API调用,调用timers,或调用process.nextTick,然后开始处理事件循环,下面是一个经典的事件循环操作顺序

┌───────────────────────────────────┐
┌─>│timers(计时器)执行                  │
│  |setTimeout以及setInterval的回调     │
│  └──────────┬────────────────────────┘
│  ┌──────────┴────────────┐
│  │     I/O callbacks     │
│   处理网络,流,TCP的错误  │  
│  │      callback      │
│  └──────────┬────────────┘
│  ┌──────────┴────────────┐
│  │     idle, prepare     │
│  │    node内部使用        │
│  └──────────┬────────────┘      ┌───────────────┐
│  ┌──────────┴────────────┐      │   incoming:   │
│  │poll(轮询)            │<─────┤  connections, │
│  │ 执行poll中的i/o队列检查 │      │data, etc.    │
│  │定时器是否到时          │      └───────────────┘
│  └──────────┬────────────┘          
│  ┌──────────┴────────────┐      
│  │        check          │
│  │  存放setImmediate回调  │
│  └──────────┬────────────┘
│  ┌──────────┴────────────┐
└──┤    close callbacks    │
   │ 关闭的回调例如         │
   │ socket.on('close')    │
   └───────────────────────┘
复制代码

其中,每个盒子都是 Event Loop的一个阶段,当Event Loop进入到某个阶段的时候,就会将该阶段队列里的回调拿出来执行,直到队列为空。

几个队列

Timers Queue - 计时器队列
I/O Queue - 输入输出队列
Check Queue - 检查队列
Close Queue - guangbi 队列
复制代码

除了上面循环阶段的任务类型,还有浏览器和nodejs共有的微任务(micro task)和node的 process.nextTick。分别称其对应的队列为MircoTask Queue和NextTick Queue

4. 开始循环之后:

依据上述6个阶段依次执行,每次拿出当前阶段的全部任务执行,清空NextTick队列,清空微任务队列,再执行下一阶段,全部6个阶段完毕后,进入下一轮的循环。

即用一张图表述为

浅谈Node.js的事件环(event loop)
  1. 结合代码
let fs = require('fs');
setTimeout(function(){
   Promise.resolve().then(()=>{
       console.log('then2');
   })
},0);
Promise.resolve().then(()=>{
   console.log('then1');
});
fs.readFile('./gitigore',function(){
   process.nextTick(function(){
       console.log('nextTick')
   })
   setImmediate(()=>{
       console.log('setImmediate')
   });
});
复制代码

回看我们开头展示的代码,这里我们的队列中显然包含有

setTimeout
Promise.resolve().then
fs.readFile
复制代码

这样的三个主要的任务队列 依据循环阶段,我们将代码按照循环阶段的顺序展示和执行

// 清空TimerQueue
setTimeout(...)  
// 清空该进程中的微任务
// then1位置的Promise先进入任务队列
Promise.resolve().then(()=>{ 
   console.log('then1'); // then1
});
Promise.resolve().then(()=>{
    console.log('then2'); // then2
})
// 接着进入IO队列
fs.readFile(...)
// 优先清空IO队列的NextTick Queue
process.nextTick(function(){
   console.log('nextTick') // nextTick
})
// 清空micro queue
setImmediate(()=>{
   console.log('setImmediate')//setImmediate
});

复制代码

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

The Haskell School of Expression

The Haskell School of Expression

Paul Hudak / Cambridge University Press / 2000-01 / USD 95.00

Functional programming is a style of programming that emphasizes the use of functions (in contrast to object-oriented programming, which emphasizes the use of objects). It has become popular in recen......一起来看看 《The Haskell School of Expression》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

随机密码生成器
随机密码生成器

多种字符组合密码

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具