内容简介:我们都知道JavaScript是单线程的,这是它语音特性决定的,因为的主要用途 在于一些I/O操作,Dom操作等,单线程为它提高了效率,但同时有很多操作,比如读取文件,Ajax获取数据等,都是一些比较耗时的操作,用户等不了太长时间,因此衍生出了事件循环这个概念。在JavaScript中,我们把队列分为两种,一种是同步任务,在主线程是执行,只有一个任务执行完才可以执行下一个任务,一种是异步任务,它不进入主线程,而是通过另外一种方式,叫做例如上图中
我们都知道JavaScript是单线程的,这是它语音特性决定的,因为的主要用途 在于一些I/O操作,Dom操作等,单线程为它提高了效率,但同时有很多操作,比如读取文件,Ajax获取数据等,都是一些比较耗时的操作,用户等不了太长时间,因此衍生出了事件循环这个概念。
1.2 任务队列
在JavaScript中,我们把队列分为两种,一种是同步任务,在主线程是执行,只有一个任务执行完才可以执行下一个任务,一种是异步任务,它不进入主线程,而是通过另外一种方式,叫做 任务队列
例如上图中
- 所有同步任务在Stack(栈)中执行
- 其他耗时操作在下面的Queue(队列)中执行,一旦这些耗时操作执行完,就会放入队列中,先进先出
- 一旦执行栈中任务执行结束,系统开始读取在队列中排队的任务,每访问一个队列,会执行完全部相同代码,比如setTimeout定时队列,再去下一个队列
- 整个过程不停循环,称为事件循环
2 Node.js
2.1 事件循环
Node.js中也有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
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 开发六大定律,比如项目总会延期
- 为什么无能的管理者总会被晋升?
- 每次修 Python 代码的 bug 的时候总会想念 Rust
- 总会用到的系列(二):你不理财财不理你的基金定投
- 008.Python循环for循环
- 006.Python循环语句while循环
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。