• 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')
      })
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    打印结果: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')
      })
    })
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    打印结果: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')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    打印结果: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')
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

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

    const fs = require('fs')
    
    fs.readFile('./m1.js', () => {
      setTimeout(() => {
        console.log('timeout')
      }, 0)
      
      setImmediate(() => {
        console.log('immdieate')
      })
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

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

  • 相关阅读:
    使用docker-compose部署wordpress
    java_ 多线程知识笔记(一)
    linux查看串口信息tty*
    软件测试 | 接口自动化你不懂?听HttpRunner的作者怎么说
    计算机网络 第3章 作业1
    社群运营的9个有效玩法 沈阳新媒体运营培训
    04.智慧商城——短信验证码倒计时、登录请求、响应拦截器统一处理、请求loading效果
    firewalld高级配置
    十九、【文本编辑器(五)】排版功能
    Python函数
  • 原文地址:https://blog.csdn.net/qq_42308316/article/details/127999208