• NodeJS事件环


    *微任务: promise.then < process.nextTick(先)
    1. 主执行栈队列
    2. timer队列: setTimeout/setInterval // 到时间后,将任务加入timer队列;没有到时间,且check队列为空,就切换到poll队列等待
    3. poll队列: i/o接口,fs.readFile //如果check队列为空,会在此阶段等待定时器到达
    4. check队列: setImmediate

    1. 执行顺序说明

    node10及之前和node11之后的“微任务队列清空条件”不同:
    1)node10及之前的版本,队列切换时才会清空微任务队列
    2)node11及之后的版本,每执行一个宏任务就清空微任务队列(同浏览器)

    1. node V10(每次切换都清空队列)

    1. 清空主执行栈队列

    2. 清空微任务队列。

    3. 按照timer->poll->check队列执行,只要执行队列切换就清空微任务队列。则主执行栈切换到timer队列,也会先清空微任务队列。

    4. 定时器时间到达,清空所有的timer队列。

    5. 如果定时器时间未到达,到poll队列,查看check队列是否有任务,如果有,清空。否则,在poll队列等待。

    6. 轮训timer队列是否有任务。

    2. node V11+ (执行一次宏任务就清空微任务队列)

    同浏览器事件环

    1. 清空主执行栈队列

    2.清空微任务队列

    3.按照timer->poll-check队列。如果timer定时器时间不到,进入poll队列执行,然后检查check队列,有任务的话,先执行第一个,然后检查微任务队列,如果有任务则清空,再继续执行check队列的其他任务,每执行一次都要清空微任务队列;否则继续等待,直到定时器到达。

    4.如果定时器时间到达,如果timer队列有多个任务,先执行第一个,然后取清空微任务队列,然后继续执行,每执行一个timer中的任务就清空一次微任务队列。

    5.再进入poll队列,依timer->poll-check轮训

    2. 应用

     示例1:

    setTimeout(() => {
        console.log('timeout')
    })
    setImmediate(() => {
        console.log('immediate')
    })
    
    // node命令执行后,先后顺序不一定。根据setTimeout定时器的到达时间快慢。
    // 如果setTimout回调函数先进入队列,先执行;否则setImmediate先执行

     示例2:

    const fs = require('fs');
    fs.readFile('1.txt', 'utf-8', function() {
        process.nextTick(() => {
            console.log('nexttick')
        })
        setTimeout(() => {
            console.log('settimeout')
        })
        setImmediate(() => {
            console.log('setImmediate')
        })
    })
    // 运行结果如下:
    nexttick
    setImmediate //按照事件环,一定先执行;因为fs是poll队列,poll队列->check队列
    settimeout

    示例3:

    process.nextTick(() => {
        console.log('nexttick')
    })
    setTimeout(() => {
        console.log('settimeout1')
    })
    setTimeout(() => {
        console.log('settimeout2')
    })
    setImmediate(() => {
        console.log('setImmediate')
        process.nextTick(() => {
            console.log('immediate->nexttick')
        })
    })
    const fs = require('fs');
    fs.readFile('1.txt', 'utf-8', function() {
        process.nextTick(() => {
            console.log('fs->nexttick')
        })
        setTimeout(() => {
            console.log('fs->settimeout')
        })
        setImmediate(() => {
            console.log('fs->setImmediate')
        })
    })
    fs.readFile('1.txt', 'utf-8', function() {
        process.nextTick(() => {
            console.log('fs2->nexttick')
        })
        setTimeout(() => {
            console.log('fs2->settimeout')
        })
        setImmediate(() => {
            console.log('fs2->setImmediate')
        })
    })
    
    // node V10运行结果如下:
    nexttick
    settimeout1
    settimeout2
    fs->nexttick
    fs2->nexttick
    setimmediate
    fs->setImmediate
    fs2->setImmediate
    immediate->nexttick
    fs->settimeout
    fs2->settimeout

    // node V11运行结果如下
    nexttick
    settimeout1
    settimeout2
    fs->nexttick
    fs2->nexttick
    setimmediate
    immediate->nexttick fs->setImmediate fs2->setImmediate fs->settimeout fs2->settimeout
     
  • 相关阅读:
    VINTF
    Excel 公式
    SSIS ODBC方式连接mysql数据库
    SSIS错误汇总
    linux防火墙(转)
    如何查询域名的MX、A、DNS、txt、cname记录
    IP反向解析
    Visual Studio 内存泄漏检测方法
    strcpy慎用
    main函数前后执行代码
  • 原文地址:https://www.cnblogs.com/lyraLee/p/11867953.html
Copyright © 2020-2023  润新知