浅谈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
});

复制代码

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

查看所有标签

猜你喜欢:

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

百面机器学习

百面机器学习

诸葛越、葫芦娃 / 人民邮电出版社 / 2018-8-1 / 89.00元

人工智能领域正在以超乎人们想象的速度发展,本书赶在人工智能彻底占领世界之前完成编写,实属万幸。 书中收录了超过100道机器学习算法工程师的面试题目和解答,其中大部分源于Hulu算法研究岗位的真实场景。本书从日常工作、生活中各种有趣的现象出发,不仅囊括了机器学习的基本知识 ,而且还包含了成为出众算法工程师的相关技能,更重要的是凝聚了笔者对人工智能领域的一颗热忱之心,旨在培养读者发现问题、解决问......一起来看看 《百面机器学习》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具