1. 只有一個主線程,node開始執行腳本時,會先進事件循環初始化(同步任務,發出異步請求,規划定時器生效時間,執行promise.nextTick等),這時事件循環還未開始。
nodejs運行機制:
- V8引擎解析js腳本
- 解析后的代碼調用Node API
- libuv庫負責Node API的執行,它將不同的任務分配給不同的線程,形成一個Event Loop,以異步的方式將任務的執行結果返回給V8引擎
- V8引擎再將結果返回給用戶
2. nodejs每一輪事件循環的六個階段(事件循環會無限次執行,直到異步任務的回調函數隊列清空才會停止執行):
- timers(處理setTimeout和setInterval的回調函數)
- I/O callbacks(除了setTimeout、setInterval、setImmediate、用於關閉請求的回調函數)
- idle,prepare(libuv內部使用)
- poll(等待還未返回的I/O事件)
- check(setImmediate)
- close callbacks(執行關閉請求的回調,如socket.on('close', ...))
3. setTimeout和setImmediate:
由於setTimeout第二個參數默認為0,但是加上node做不到真正的0ms,最少也需要1s;所以實際執行進入事件循環后,如果沒到1ms,那么timers階段就會跳過進入check階段,所以執行順序不確定。
4. 異步任務分兩種:
本輪循環:promise.nextTick、promise的回調函數
次輪循環:setTimeout、setInteval、setImmediate的回調函數
5. 多個process.nextTick語句總是在當前"執行棧"一次執行完,多個setImmediate可能則需要多次loop才能執行完;
6. 為什么process.nextTick 永遠大於 promise.then?因為Node中,_tickCallback在每一次執行完TaskQueue中的一個任務后被調用,而這個_tickCallback中實質上干了兩件事:
- nextTickQueue中所有任務執行掉(長度最大1e4,Node版本v6.9.1)
- 第一步執行完后執行_runMicrotasks函數,執行microtask中的部分(promise.then注冊的回調)
