node.js是什么
是一個基于Chrome V8引擎的JavaScript運行環(huán)境
1.非阻塞
Node.js標準庫中的所有 I/O 方法都提供異步版本,即非阻塞,并接受回調(diào)函數(shù)。一些方法還具有阻塞對應項,其名稱以 .Sync。
2.V8引擎
blink渲染,

3.線程與事件循環(huán)
進程 - 系統(tǒng)資源分配,有自己獨立的地址空間,一個進程有多個線程,分別執(zhí)行不同任務(wù)。進程之間不能共享資源,而線程共享所在進程的地址空間和其它資源。同時線程還有自己的棧和棧指針,程序計數(shù)器等寄存器。
線程 - cpu調(diào)度單位,它包含在進程中,是進程運行的最小單位,線程依賴進程存在,線程的切換開銷相對較小
node得運行機制
主線程一個,底層工作線程有多個。
js通過V8引擎調(diào)用node API,node API底層由c++ libuv庫實現(xiàn),libuv庫將接收到的不同異步操作分配給不同的線程,不同線程處理結(jié)束后已異步方式,將結(jié)果返回給v8引擎。
js任務(wù)分為同步任務(wù)和異步任務(wù),異步任務(wù)分為微任務(wù)與宏任務(wù)。
1、主線程執(zhí)行棧全部任務(wù)執(zhí)行完畢。
2、檢查微任務(wù)隊列,process.nextTick優(yōu)先級最高,總是最先執(zhí)行。
3、檢查宏任務(wù)隊列,提取一次任務(wù)推入執(zhí)行棧,進行執(zhí)行。

右側(cè)宏任務(wù)隊列才是事件循環(huán)的關(guān)鍵。事件循環(huán)就是為了解決異步操作。所以同步任務(wù)不屬于事件循環(huán),同時微任務(wù)也不屬于事件循環(huán)的一部分。
事件循環(huán)如圖分為6個階段,每個階段為一個FIFO回調(diào)隊列(可理解為回調(diào)函數(shù)數(shù)組),按圖順序依次執(zhí)行。事件循環(huán)每進入一個階段,則將該階段的回調(diào)隊列用盡(全部執(zhí)行完畢)或到最大限制回調(diào)數(shù),則進入下一階段。
列:
//宏任務(wù) check階 暫時命名任務(wù)1 setImmediate方法用于將任務(wù)放入事件循環(huán)中的check階段
setImmediate(()=>console.log(1))
//宏任務(wù) timer階段暫時命名任務(wù)2
setTimeout(()=>{
console.log(2);
//宏任務(wù) timer階段 時命名任務(wù)22
setTimeout(()=>{
console.log(22)
},1.0);
//宏任務(wù) timer階段暫時命名任務(wù)3
setTimeout(()=>{console.log(3);})
},1.8);
//宏任務(wù) timer階段暫時命名任務(wù)4
setTimeout(()=>{
console.log(4);
},100);
//微任務(wù)
//暫時命名任務(wù)5
process.nextTick(()=>console.log(5));
//同步任務(wù)
//暫時命名任務(wù)6
console.log(6);console.log(7);//執(zhí)行結(jié)果為 6 7 5 2 3 1 22 4
步驟1 首先根據(jù)js執(zhí)行順序,從上到下依次執(zhí)行,發(fā)現(xiàn)宏任務(wù)將任務(wù)放入下一個事件循環(huán)中,發(fā)現(xiàn)微任務(wù),將其置入微任務(wù)隊列中。將同步任務(wù)置入執(zhí)行棧中。
步驟2 開始運行執(zhí)行棧,其中有兩行同步語句,輸出 6 7,此時執(zhí)行棧中運行完畢,主線程空閑;
步驟3 開始檢查微任務(wù)隊列,微任務(wù)隊列中包含 process.nextTick,則輸出5,微任務(wù)隊列執(zhí)行全部執(zhí)行完畢,隊列中再無其他微任務(wù),則檢查宏任務(wù)隊列開始進行事件循環(huán)。
步驟4 事件循環(huán)進入第一階段(timer階段),檢查是否有定時器超時的回調(diào),此時發(fā)現(xiàn)隊列中有兩個回調(diào)(任務(wù)2和任務(wù)3回調(diào))。
先執(zhí)行任務(wù)2回調(diào),輸出 2。發(fā)現(xiàn)宏任務(wù)22,則將該任務(wù)放入下一次事件循環(huán)中(同步驟1。也同時符合執(zhí)行一個宏任務(wù)則繼續(xù)運行執(zhí)行棧和微任務(wù)的解釋)。
步驟5 任務(wù)2回調(diào)執(zhí)行完畢,繼續(xù)執(zhí)行任務(wù)3回調(diào)。 (注意所有異步操作是后臺操作完成可以觸發(fā)回調(diào)函數(shù)時,才將回調(diào)函數(shù)放入對應階段的隊列中。所以此時timer隊列中并無任務(wù)4回調(diào)) 。
步驟6 timer隊列清空,事件循環(huán)進入下一階段,依次到check階段之前均為空隊列,進入check階段,執(zhí)行任務(wù)1回調(diào),輸出1。繼續(xù)進入close callback階段。結(jié)束本次事件循環(huán)。
步驟7 進入下一個事件循環(huán),timer階段,隊列中任務(wù)22回調(diào),輸出22。繼續(xù)進入下面階段,直到循環(huán)結(jié)束。
繼續(xù)進入下一循環(huán)。。直到任務(wù)4超時回調(diào)觸發(fā) 輸出 4。