例子
首先從一個例子開始nodejs的事件循環
const { readFile } = require('fs')
const { resolve } = require('path')
const EventEmitter = require('events')
class EE extends EventEmitter {}
const instance = new EE()
instance.on('jhs', () => {
console.log('jhs事件回調調用')
})
setTimeout(() => {
console.log('0 ms 後到期執行的定時器回調')
}, )
setTimeout(() => {
console.log('100 ms 後到期執行的定時器回調')
}, )
setTimeout(() => {
console.log('200 ms 後到期執行的定時器回調')
}, )
readFile(resolve(__dirname, '../package.json'), 'utf-8', () => {
console.log('第1次讀取檔案操作回調')
})
readFile(resolve(__dirname, '../README.md'), 'utf-8', () => {
console.log('第2次讀取檔案操作回調')
})
setImmediate(() => {
console.log('immediate 立即回調')
})
process.nextTick(() => {
console.log('process.nextTick 的第 1 次回調')
})
Promise.resolve().then(() => {
instance.emit('jhs')
process.nextTick(() => {
console.log('process.nextTick 的第 2 次回調')
})
console.log('promise的第 1 次回調')
}).then(() => {
console.log('promise的第 2 次回調')
})
- 參考下官網的The Node.js Event Loop, Timers, and process.nextTick()解釋https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/
-
牆裂推薦阮老師的部落格 http://www.ruanyifeng.com/blog/2018/02/node-event-loop.html
看完後,能否試圖對上面的例子運作結果做出預判呢。
執行解釋
首先,目前是本輪循環。在第一個階段之前,已經有了line 37 process.nextTick回調注冊,是以第一個列印是 process.nextTick 的第 1 次回調 。執行完後執行Promise.resolve,它是僅次于process.nextTick的優先級。在line 41 Promise.then裡第一個執行的是instance.emit(‘jhs’),觸發了事件回調,于是立刻執行line 9 的instance.on(‘jhs’注冊的回調函數,列印 jhs事件回調調用 ,執行完畢後會回到line 43,又遇到 process.nextTick, 下面列印 promise的第 1 次回調。繼續往下走會列印 promise的第 2 次回調。在line 48 執行完後,因為剛才又新加了一個process.nextTick,是以目前事件循環體裡還有一個nextTick未執行,優先執行它,是以列印 process.nextTick 的第 2 次回調 。列印完後,目前事件循環體裡沒有了nextTick,也沒有了promise等microtask。進入下輪循環,首先進入到times階段。是以time階段第一個執行的是line 14 這個0ms的定時器,列印 0 ms 後到期執行的定時器回調 ,這個執行完後,目前的100ms和200ms可能還沒到期,就會進到下個階段。發現poll階段裡面有兩個回調函數還沒執行,都是讀檔案操作,首先列印 第1次讀取檔案操作回調,然後 列印 第2次讀取檔案操作回調.等到這個poll隊列被執行清空以後。進入ckeck階段 發現又注冊了setImmediate回調,列印 immediate 立即回調 。最後再次前往timer階段,列印 100 ms 後到期執行的定時器回調和 200 ms 後到期執行的定時器回調。
然而,最後的運作結果如下:
process.nextTick 的第 次回調
jhs事件回調調用
promise的第 次回調
promise的第 次回調
process.nextTick 的第 次回調
ms 後到期執行的定時器回調
immediate 立即回調
第次讀取檔案操作回調
第次讀取檔案操作回調
ms 後到期執行的定時器回調
ms 後到期執行的定時器回調
發現,immediate立即回調在讀檔案操作之前執行,講道理immediate在check階段,而讀檔案操作在poll階段,懵逼臉~~~我的了解,readFile是異步不阻塞的讀檔案,不影響event loop,莫非例子中兩個檔案讀取較慢,是以進入了check階段并執行了immediate,然後這兩個讀檔案在下輪循環中執行。
還是應該深入到libuv源碼
github 搜尋 nodejs, 進入https://github.com/nodejs/node 項目後,英文輸入法下按住t 鍵,搜尋 deps/uv/src/unix/core.c,開始源碼探索之旅吧~
目前我還隻能看别人的分析,哭~~比如下面這篇分析的挺好。
3. https://cnodejs.org/topic/5a9108d78d6e16e56bb80882