Event Loop事件循环,看完你总会有点收获!

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

内容简介:我们都知道JavaScript是单线程的,这是它语音特性决定的,因为的主要用途 在于一些I/O操作,Dom操作等,单线程为它提高了效率,但同时有很多操作,比如读取文件,Ajax获取数据等,都是一些比较耗时的操作,用户等不了太长时间,因此衍生出了事件循环这个概念。在JavaScript中,我们把队列分为两种,一种是同步任务,在主线程是执行,只有一个任务执行完才可以执行下一个任务,一种是异步任务,它不进入主线程,而是通过另外一种方式,叫做例如上图中

我们都知道JavaScript是单线程的,这是它语音特性决定的,因为的主要用途 在于一些I/O操作,Dom操作等,单线程为它提高了效率,但同时有很多操作,比如读取文件,Ajax获取数据等,都是一些比较耗时的操作,用户等不了太长时间,因此衍生出了事件循环这个概念。

1.2 任务队列

在JavaScript中,我们把队列分为两种,一种是同步任务,在主线程是执行,只有一个任务执行完才可以执行下一个任务,一种是异步任务,它不进入主线程,而是通过另外一种方式,叫做 任务队列

Event Loop事件循环,看完你总会有点收获!

例如上图中

  • 所有同步任务在Stack(栈)中执行
  • 其他耗时操作在下面的Queue(队列)中执行,一旦这些耗时操作执行完,就会放入队列中,先进先出
  • 一旦执行栈中任务执行结束,系统开始读取在队列中排队的任务,每访问一个队列,会执行完全部相同代码,比如setTimeout定时队列,再去下一个队列
  • 整个过程不停循环,称为事件循环

2 Node.js

2.1 事件循环

Node.js中也有Event Loop,不过它的机制和和浏览器中的略微不同

Event Loop事件循环,看完你总会有点收获!

如上图是经典的Node.js中的事件循环图,Node.js采用谷歌V8作为解析引擎,在I/O处理方面使用了libuv库,它是一个基于事件驱动的跨平台抽象层,封装了不同操作系统一些底层特性,对外提供统一的API,上图的事件循环机制是它里面的实现。 每次事件循环都包含了六个阶段:

  • timers阶段:包括setTimeout,setInterval等
  • pedding callbacks: 执行一些系统调用错误
  • idle,prepare: node内部使用
  • poll: 轮询阶段,检查I/O队列中定时器是否到时,例如(读取文件)
  • check:执行setImmediate() 设定的callbacks
  • close callbacks: 关闭回调

其中还有一些微任务和宏任务的概念 微任务:promise.then process.nextTick(),其中nextTick()执行会比前者快 宏任务:setTimeout setImmidate(ie) messageChannel等

微任务总是会比宏任务先执行

2.2例子

setTimeout(() => {
    console.log('timeout1');
    process.nextTick(()=>{
        console.log('nextTick1');
    })
}, 1000);
setTimeout(()=>{
    console.log('timeout2')
},1000)
复制代码

结果:timeout1 => timeout2 =>nextTick1 原因:首先都是外面宏任务,先执行时间队列,从上到下依次执行完timeout1=>timeout2,执行完后,到下一个队列,执行nextTick()

let fs = require('fs');
fs.readFile('./index.html',function(){ 
    setImmediate(function(){
        console.log('setImmediate')
    });
    setTimeout(function(){
        console.log('setTimeout')
    },0); // ->4
})
复制代码

结果:setImmediate => setTimeout 原因:读取文件是I/O操作是在poll轮询阶段,读取完后下一阶段是check,看有没有setImmediate,所以先执行这个,再执行setTimeout

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

复制代码

结果:then1 => then2=> nextTick => setImmediate 原因:首先看最外面有微任务Promise.then,所以then1,接着到时间队列,times,执行then2,times => poll 是不同阶段,每执行不同阶段, process.nextTick 不属于事件循环的任何一个阶段,它属于该阶段与下阶段之间的过渡, 即本阶段执行结束, 进入下一个阶段前, 所要执行的回调。所以 都要检查当前有没有promise,或者nextTick,如果有,先执行这些,有nextTick,再执行setImmediate


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

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

趋势红利

趋势红利

刘润 / 文化发展出版社(原印刷工业出版社) / 2016-6-1 / 45.00

【编辑推荐】 1、国内顶尖的互联网转型专家,海尔、百度等知名企业战略顾问刘润送给传统企业的转型、创新“导航仪”,这个时代企业家的必修课 站在近200年商业全景图角度,刘润发现三种企业类型(产品型、渠道型、营销型),针对不同企业类型定制转型战略(找到自己的未来红利),方便 传统企业对号入座:不走错路就是节省时间,适合自己的最有效率。 本书内容还源自芬尼克兹、红领集团、名创优品、必要......一起来看看 《趋势红利》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具