node event loop

Lena發表於2018-08-24

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,所有結果不會是隨機的

相關文章