node event loop

168 阅读3分钟

node event loop

目前考虑的就是

  • timer (setTimeout setInterval),
  • i/o操作,
  • check阶段的seImmediate

首先要确定下这三个阶段的顺序

1.文件里只有setTimeout(且时间设置为0) 和setImmediate

setTimeout(() => {
    console.log('setTimeout')
}, 0);
setImmediate(function(){
    console.log('seimmediate')
})

这种情况打印的先后顺序是不确定的,主要是该文件准备需要消耗一定时间,如果大于4,当遇到setTimout的时候,就直接执行,之后是setImmediate。如果消耗时间小于4,则setTimeout还未到执行时间,执行check阶段的setImmediate,到了4,再去执行setTimeout

2.文件里有setTimeout fs,和setImmediate

setInterval(() => {
    console.log('setTimeout')
}, 3);


var n = Date.now()
fs.readFile('work.html',function(){
    var fileTime = Date.now() - n
    // console.log(fileTime)
    // console.time('start')
    // for(let i =0;i<100;i++){
    //     console.log('no')
    // }
    // console.timeEnd('start')
    console.log('fs')
    
})

setImmediate(function(){
    console.log('setImmediate')
})

现在我们把其中的两个静态值改为动态值,方便大家理解。time:定时器的时间(本文件是3),fileTime是读取work.html的时间,stackTime指同步代码执行需要时间
代码的执行顺序和time大小和file大小有关

  • time < stackTime时(time=0时),栈里内容执行完后,清空timer阶段队列,然后执行i/o的读取,但发现下面有check阶段,则优先check
    故打印顺序为 setTimeout 、setImmediate、fs

  • time > stackTime && time < fileTime时,还没有到时间的定时器,timer队列为空,直接走i/o的读取,但发现下面有check阶段,则优先check,之后继续读取文件,期间检查到有到时间的定时器,则会优先执行timer,之后继续读取文件,读完之后,执行callback
    故打印顺序为 setImmediate、setTimeout、fs

  • time > stackTime && time > fileTime时,还没有到时间的定时器,timer队列为空,直接走i/o的读取,但发现下面有check阶段,则优先check,之后继续读取文件,期间没有到时间的定时器,执行callback,只有callback执行完之后(期间即使有到时间的定时器,也不会去执行),才会再去执行到时间的定时器。
    故打印顺序为setImmediate、fs、setTimeout

  • 小总结:fs分为两个阶段,一是读取阶段,二是callback执行阶段。当在读取阶段,其优先级最小,会让给其下个check阶段,期间会让给time阶段,但一旦读取文件结束,开始执行callback,则优先级增大,不会让给time阶段

上面讲到的都不包括有微任务的情况,node 里的微任务包含promise.then(),和process.nextTick()

微任务是在栈执行完,清除微任务,再进入宏任务,清除完一个宏阶段,进入下个宏阶段前,清除微任务,再进入下一个宏阶段,宏阶段的顺序就是上面降到的顺序
需要注意的是,process.nextTick()在promise.then()之前执行

来考验下大家,下面代码如何打印

fs.readFile('work.html',function(){
    setTimeout(() => {
        console.log('setTimeout2')
        // for(;;){}
    }, 0);
    setImmediate(function(){
        console.log('setImmediate2')
    })
})

揭晓答案,只有setImmediate2、setTimeout2 一种结果,不会像文件里只有setTimeout和setImmediate一样,因为,i/o操作完之后,下一个叫阶段是check,所有结果不会是随机的