带你了解NodeJS事件循环
文章图片
浏览器中存在两个任务队列,一个是宏任务一个是微任务。但是在NodeJS中一共存在六个事件队列,timers
,pending callbacks,idle prepare
,poll,check
,close callbacks
。每一个队列里面存放的都是回调函数callback
。
这六个队列是按顺序执行的。每个队列负责存储不同的任务。
timer
里面存在的是setTimeout与setInterval的回调函数pending callback
是执行操作系统的回调,例如tcp,udp。idle
和prepare
只在系统内部进行使用。一般开发者用不到poll
执行与IO相关的回调操作check
中存放setImmediate中的回调。close callbacks
执行close事件的回调。
当同步代码执行完成之后会去执行满足条件的微任务,一旦所有的微任务执行完毕就会按照上面列出的顺序去执行队列当中满足条件的宏任务。
首先会执行timers当中满足条件的宏任务,当他将timers中满足的任务执行完成之后就会去执行队列的切换,在切换之前会先去清空微任务列表中的微任务。
所以微任务执行是有两个时机的,第一个时机是所有的同步代码执行完毕,第二个时机队列切换前。
【带你了解NodeJS事件循环】注意在微任务中nextTick的执行优先级要高于
Promise
,这个只能死记了。setTimeout(() => {console.log('s1'); })Promise.resolve().then(() => {console.log('p1'); })console.log('start'); process.nextTick(() => {console.log('tick'); })setImmediate(() => {console.log('st'); })console.log('end'); // start end tick p1 s1 st
setTimeout(() => {console.log('s1'); Promise.resolve().then(() => {console.log('p1'); })process.nextTick(() => {console.log('t1'); })})Promise.resolve().then(() => {console.log('p2')})console.log('start'); setTimeout(() => {console.log('s2'); Promise.resolve().then(() => {console.log('p3'); })process.nextTick(() => {console.log('t2'); })})console.log('end'); // start end p2 s1 s2 t1 t2 p1 p3
Node
与浏览器事件环执行是有一些不同的。首先任务队列数不同,浏览器一般只有宏任务和微任务两个队列,而Node中除了微任务队列外还有6个事件队列。
其次微任务执行时机不同,不过他们也有相同的地方就是在同步任务执行完毕之后都会去看一下微任务是否存在可执行的。对浏览器来说每当一个宏任务执行完成之后就会清空一次微任务队列。在Node中只有在事件队列切换时才会去清空微任务队列。
最后在Node平台下微任务执行是有优先级的,nextTick优先于
Promise.then
, 而浏览器中则是先进先出。setTimeout(() => {console.log('timeout'); })setImmediate(() => {console.log('immdieate'); })
在Node中时而会先输出
timeout
时而会先输出immdieate
,这是因为setTimeout
是需要接收一个时间参数的,如果没写就是一个0,我们都知道无论是在Node还是在浏览器,程序是不可能真的是0,他会受很多的因素影响。这取决于运行的环境。如果setTimeout先执行就会放在timers队列中,这样timeout就会先输入,如果setTimeout因为某些原因后执行了,那么check队列中的
immdieate
就会先执行。这就是为什么时而输出timeout时而输出immdieate
。const fs = require('fs'); fs.readFile('./a.txt', () => {setTimeout(() => {console.log('timeout'); }, 0)setImmediate(() => {console.log('immdieate'); })})
这种情况就会一直先输出
immdieate
后输出timeout
,这是因为,代码执行的时候会在timers里面加入timeout, 在poll中加入fs的回调,在check中加入immdieate
。fs的回调执行结束之后实在poll队列,队列切换的时候首先会去看微任务,但是这里没有微任务就会继续向下,下面就是check队列而不是timers队列,所以poll清空之后会切换到check队列,执行immdieate回调。到此这篇关于带你了解NodeJS事件循环的文章就介绍到这了,更多相关NodeJS事件循环内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
推荐阅读
- 我们重新了解付费。
- 拍照一年啦,如果你想了解我,那就请先看看这篇文章
- C语言中的时间函数clock()和time()你都了解吗
- 不废话,代码实践带你掌握|不废话,代码实践带你掌握 强缓存、协商缓存!
- 操作系统|[译]从内部了解现代浏览器(1)
- 生发知识,带你深入了解
- 了解自然大气粒子对气候的影响
- 带你了解类型系统以及flow和typescript的基本使用
- 带你来看花
- 窝在家里,你闷坏了吗(了解这12个假设,给自己的心理增加免疫力)