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

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

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


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

查看所有标签

猜你喜欢:

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

Pro JavaScript Techniques

Pro JavaScript Techniques

John Resig / Apress / 2006-12-13 / USD 44.99

Pro JavaScript Techniques is the ultimate JavaScript book for the modern web developer. It provides everything you need to know about modern JavaScript, and shows what JavaScript can do for your web s......一起来看看 《Pro JavaScript Techniques》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试