Node与浏览器平台下的Event loop

Event loop

浏览器中的Event loop

浏览器平台下一共有两个任务队列,一个是宏任务一个是微任务。

  • 从上至下执行所有的同步代码
  • 执行过程中将遇到的宏任务与微任务添加至相应的队列
  • 同步代码执行完毕后,执行满足条件的微任务回调
  • 微任务队列执行完毕后执行所有满足需求的宏任务回调
  • 如此循环
  • 注意:每执行一个宏任务之后就会立刻检查微任务队列
setTimeout(() => {
  console.log('s1')
  Promise.resolve().then(() => {
    console.log('p1')
  })
  Promise.resolve().then(() => {
    console.log('p2')
  })
})

setTimeout(() => {
  console.log('s2')
  Promise.resolve().then(() => {
    console.log('p3')
  })
  Promise.resolve().then(() => {
    console.log('p4')
  })
})

打印结果:s1、p1、p2、s2、p3、p4

setTimeout(() => {
  console.log('s1')
  Promise.resolve().then(() => {
    console.log('p2')
  })
  Promise.resolve().then(() => {
    console.log('p3')
  })
})

Promise.resolve().then(() => {
  console.log('p1')
  setTimeout(() => {
    console.log('s2')
  })
  setTimeout(() => {
    console.log('s3')
  })
})

打印结果:p1、 s1、 p2、 p3、 s2、 s3

Nodejs中的Event loop

在浏览器平台下一共有两个任务队列,一个是宏任务一个是微任务。但在node下一共是有6个队列,如下
在这里插入图片描述

node中的6个队列说明
  • timers宏任务队列: 执行setTimeout与setInterVal回调
  • pending callbacks: 执行系统操作的回调,例如tcp、udp
  • idle,prepare: 只在系统内部进行使用
  • poll: 执行与I/O相关的回调
  • check: 执行setInnediate中的回调
  • close callbacks: 执行close事件的回调
Nodejs完整时间环
  • 执行同步代码,将不同的任务添加至相应的队列
    • 比如 遇到setTimeout会把任务添加到timers中,遇到I/O会把任务添加到poll中
  • 所有同步代码执行后会去执行满足条件的微任务
  • 所有微任务代码执行后会执行timer队列中满足的宏任务
  • timer中的所有宏任务执行完成后就会依次切换队列
  • 注意:在完成队列切换之前会清空微任务代码
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、t1、p1、s2、t2、p3
小结: process.nextTick是微任务,它的执行顺序优先于Promise.then。 而且在旧版中node的执行顺序是需要等宏任务队列执行完再执行微任务的也就是start、end、p2、s1、s2、t1、t2、p1、p3。 在新版node中改为与浏览器保持一致了

Nodejs与浏览器Event loop的区别

  • 任务队列数不同
    • 浏览器中只有2个任务队列.宏任务与微任务
    • Nodejs中除了微任务还有6个事件队列
  • Nodejs微任务执行时机不同(新版node改为一致了)
    • 二者都会在同步代码执行完毕后执行微任务
    • 浏览器平台下每当一个宏任务执行完毕后就清空微任务
    • nodejs平台在事件队列切换时会去清空微任务
  • 微任务优先级不同
    • 浏览器事件环中,微任务存放于事件队列,先进先出
    • Nodejs中process.nextTick先于promise.then

Nodejs Event loop常见问题

setTimeout不管是在浏览器平台下还是在node平台下,它的第二个参数如果不传默认是0,而传0的话会有些不稳定因素,就会造成延时可能在setImmediate之后的情况。当我们不停的执行下面这段代码时就会偶现immdieate现被打印的情况。

setTimeout(() => {
  console.log('timeout')
})

setImmediate(() => {
  console.log('immdieate')
})

但是如果将同样的代码放到文件读取之后的回调中顺序又会是始终一致。如下

const fs = require('fs')

fs.readFile('./m1.js', () => {
  setTimeout(() => {
    console.log('timeout')
  }, 0)
  
  setImmediate(() => {
    console.log('immdieate')
  })
})

原因是fs.readFile是一个poll事件队列。这个队列的执行顺序如下
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值