今天我們來學習一下,瀏覽器的事件環(eventLoop)和node的事件環,它們之間有什麼區別,這也是面試常問的知識,所以一定要仔細看哦,寫的不好的地方,歡迎大家指正。
一、瀏覽器事件環
1、js是單執行緒的嗎?
我們都知道js是單執行緒的,當然這句話說的不是很對,應該說它的主執行緒是單執行緒的。例如:ajax和setTimeout在瀏覽器中就會多開一條執行緒。
2、非同步裡的概念(巨集任務和微任務)
在JavaScript中,任務被分為Task(又稱為MacroTask,巨集任務)和MicroTask(微任務)兩種。它們分別包含以下內容:
巨集任務:setTimeout setInterval setImmediate(ie下生效) MessageChannel(訊息通道)
微任務:Promise.then MutationObserver(監聽dom節點更新完畢) process.nextTick()(node的文法,比Promise.then執行的快)
我們來寫程式碼證明一下,巨集任務和微任務哪個執行比較快。
setTimeout(()=>{
console.log('setTimeout')
},0)
Promise.resolve().then(()=>{
console.log('promise')
})
promise setTimeout //promise在setTimeout之前輸入,證明Promise.then執行較快複製程式碼
3、js的執行順序
程式碼從上到下執行,會先執行同步的程式碼,再執行微任務,等待巨集任務有沒有到時間,時間到了的巨集任務放到巨集任務佇列,微任務執行完畢後,會從巨集任務佇列中取出一個巨集任務去放到當前的瀏覽器的執行環境中執行,當前執行環境都執行完畢後,會先去清空微任務,下面我們來看一段程式碼
setTimeout(()=>{
console.log('timeout1');
Promise.resolve().then(data=>{
console.log('then1')
})
},0)
Promise.resolve().then(data=>{
console.log('then2')
setTimeout(()=>{
console.log('timeout2');
},0)
})
//then2 timeout1 then1 timeout2複製程式碼
二、node事件環
1、node.js中對於事件環的解釋
我們先來看一張官方文件的圖片,然後來解釋它們都是幹什麼的。node的事件環和我們瀏覽器的不太一樣,它給每一個任務都配了一個佇列,如下圖。
- timers: 定時器setTimeout和seInterval的執行,將callback加入佇列中。
- pending callbacks: 一些I/O的callback,推遲到下一次迴圈中執行。
- idle, prepare: 內部的一些事件。
- poll: 輪循,i/o,回撥,fs.readFile()。
- check: setImmediate的callback執行。
- close callbacks: 一,些關閉的回撥函式,如socket。
其實我們需要關心的就是timers、poll、check這三個階段。下面我們來說一下它們的執行順序。
- 預設,會從上到下依次執行,如果程式碼執行到poll後,發現check階段沒有,那就在poll在等待,等待times時間到達後,再清空程式碼。
- 只到佇列發生切換時,就會執行微任務。
- poll的下一個階段就是check,如果check佇列中有東西的,會先執行check。
下面我們來看幾段程式碼,實現一下我們上面的論證。
setTimeout(()={
console.log("time1");
process.nextTick(()=>{
console.log("nextTick2");
});
});
console.log("start")
process.nextTick(()=>{
console.log("nextTick1");
setTimeout(()={
console.log("time2");
});
});
//
//start nextTick1 time1 time2 nextTick2 //node11儘量和瀏覽器的相同
//start nextTick1 time1 nextTick2 time2 //node10會出現這種輸出上複製程式碼
上面的程式碼在node10的版本里會輸出兩種不同的結果,node11裡就只會輸出第一種,node11在儘量的和瀏覽器相同。
setImmediate(()=>{
console.log('setImmediate')
});
setTimeout(()=>{
console.log('timeout')
})
//setImmediate timeout
//timeout setImmediate複製程式碼
上面的程式碼會出現這兩種輸出結果,不一定誰先輸出誰後輸出。
fs.readFile('./name.txt','utf8',()=>{
setImmediate(()=>{
console.log('setImmediate')
});
setTimeout(()=>{
console.log('timeout')
})
})
//setImmediate timeout複製程式碼
上面的程式碼就一定會先輸出setImmediate,因為readFile在poll階段,它的下一個階段一定是check,所以一定會先輸出setImmediate。
好了,我們的瀏覽器事件環和node事件環就說到這裡了,不明白的小夥伴動手敲一下,就會好很好多哦。。。