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

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

内容简介:我们都知道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


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

查看所有标签

猜你喜欢:

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

人本界面

人本界面

(美)拉斯基(Jef Raskin) / 史元春 / 机械工业出版社 / 2004-1-1 / 28.0

如果我们想克服目前人机界面上的固有缺陷,就很有必要理解本书的教义;若无此愿望,读读也无妨。交互设计的许多重要方面此书并没有包括在内,因为许多文献中都已经有详尽的阐述。本书的意图是补充现有的界面设计的方法或预测未来。  本书概述了人机界面设计领域的研究成果,详细论证了界面设计思想应以认知学为基础,并考虑人类的心智特点,在指出当前界面设计中弊端的同时,提出了新产品开发的思路。本书集计算机科学、人体工程......一起来看看 《人本界面》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

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

UNIX 时间戳转换

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具