iT邦幫忙

2

【我可以你也可以的Node.js】第六篇 - Node's EventLoop和Node程式執行順序

嗨各位大大~
我是Robin
這週來分享一下我這週學習的Node's EventLoop


本篇學習目標◑ω◐:

  • 初步試探Node同步異步執行順序
  • 認識 Node’s EventLoop
  • 驗收

初步試探Node同步異步執行順序

先試試看在讀這篇的你對於node中同步異步的掌握。
試著把以下的順序寫下來

// foo.js
setTimeout(() => console.log(1));

setImmediate(() => console.log(2));

Promise.resolve().then(() => console.log(3));

process.nextTick(() => console.log(4));

(() => console.log(5))();

想好答案了嗎?
答案會是

5
4
3
1 //有可能是2
2 //有可能是1

如果你答對了(猜對不算)!(๑• . •๑)
恭喜你可以把文章關掉了(反正點閱已經被我騙到了)
完全正確也可以接著看我的文章驗證自己和我的敘述的是否相同啦~
沒有答對的不要氣餒讓我們一起學習吧~(●´ω`●)ゞ

Node’s EventLoop 初步認識

接續上篇的JS使用的EventLoop,
在Node中又有什麼不同?
我會以我的觀察來分享一下。

他們聽起來是一樣的,( ͡° ͜ʖ ͡°)
但是實際實作方式真的是相差甚遠Σ(゚Д゚;≡;゚д゚)
Node跟瀏覽器的EventLoop比複雜許多。
Node的EventLoop是基於libuv函式庫實作出的

libuv是使用C++寫出來的,聽說這個函示庫一開始就是為了node而寫的。

我們來看看官方文件說了啥(,,・ω・,,)

When Node.js starts, it initializes the event loop, processes the provided input script (or drops into the REPL, which is not covered in this document) which may make async API calls, schedule timers, or call process.nextTick(), then begins processing the event loop.

歸納出當一支Node程式執行時執行順序

1. 初始化事件循環
2. 同步任務
3. 提出異步任務的請求
4. 規劃定時器的生效時間
5. 執行process.nextTick()
6. 開始事件循環

Node中異步任務有分本輪循環次輪循環

這邊你只要知道本輪循環一定比次輪循環還要早執行就對了。

上述的process.nextTick()的回調(callback)是屬於本輪循環的,千萬不要被他的名詞給騙去了(๑¯∀¯๑)

而除此之外還有微任務,就是指Promise的回調函數(callback) ,他也是跟process.nextTick()的回調一樣屬於本輪循環
然後他會在process.nextTick()的回調後執行。
而以下這些回調函數(callback)會加在次輪循環

setTimeout
setInterval
setImmediate

而Node中EventLoop分為六個階段(如圖)

而他們會依序執行圖中的

1. timeers
2. pending callbacks
3. idlem prepare
4. poll
5. check
6. close callbacks

然後他們各自是幹嘛的?借用一下這篇的內容

各 Phase 的責任說明
timer:執行由 setTimeout() 及 setInterval() 排進來的 callbacks
I/O callbacks:有關系統錯誤等 Callbacks 將 queue 在此
idle, prepare:內部使用
poll:向系統取回新的 I/O 事件,執行對應的 I/O callbacks
check:執行由 setImmediate() 排進來的 callbacks
close callbacks:監聽 I/O 'close' 事件的 callbacks (如 socket.on('close', ...))

看完上面的敘述應該會有一點點概念他執行順序...
詳細有興趣可以自行再深入研究或底下留言討論。
想想上一篇瀏覽器的單純時光,那是我逝去的青春

驗收

看完以上來看看自己對於Node的同步非同步執行順序應該是略知一二了。
來驗收看看囉
一樣寫下來看答案對不對~

console.log("A");

setTimeout(() => console.log(1));

console.log("B");

setImmediate(() => console.log(2));

console.log("C");

process.nextTick(() => console.log(4));

console.log("D");

Promise.resolve().then(() => console.log(3));

console.log("E");

(() => console.log(5))();

答案

A
B
C
D
E
5
4
3
1 //有可能是2
2 //有可能是1

看完以上你應該會想說
靠北你還是沒說為什麼會有“可能是1可能是2的情況啊”
這邊轉貼一下別人的說明來源

这是因为setTimeout的第二个参数默认为0。但是实际上,Node 做不到0毫秒,最少也需要1毫秒,根据官方文档,第二个参数的取值范围在1毫秒到2147483647毫秒之间。
也就是说,setTimeout(f, 0)等同于setTimeout(f, 1)。

实际执行的时候,进入事件循环以后,有可能到了1毫秒,也可能还没到1毫秒,取决于系统当时的状况。如果没到1毫秒,那么 timers 阶段就会跳过,进入 check 阶段,先执行setImmediate的回调函数。

如果你沒有想到
沒關係

以上純屬開玩笑
不要告我

本週心得

我還是不要在每篇底下說我下篇要寫什麼好了xDD
每次立Flag,然後一直拆整篇的內容感覺很愧對各位大大 Orz
原本這篇要講滿多東西的但是這週有點忙直接拆了1/3
對不起QQ

參考文獻

Banner設計
Node官方 Document
深入理解js事件循环机制(Node.js篇)
What is the different between JavaScript Event loop and Node.js Event loop?


1 則留言

1
Sam
iT邦新手 5 級 ‧ 2020-03-16 11:31:50

我還是不要在每篇底下說我下篇要寫什麼好了xDD
每次立Flag,然後一直拆整篇的內容感覺很愧對各位大大 Orz

在文章底下預言下篇內容,壓力真的很大 XD

我要留言

立即登入留言