Event Loop指的是計算機系統的一種執行機制。JavaScript採用此機制解決單執行緒引發相關問題
在瀏覽器中的web應用會涉及到.JavaScript引擎、WebAPI、Event Loop、Task Queue (Macro Task, Micro Task).因此如果想弄清Event Queue.我們必須都以上都有所瞭解.
JavaScript引擎:
目前市面上解析JavaScript檔案效率最高的就是Google的V8引擎.它主要由兩個部分組成:
- 記憶體堆: 負責記憶體分配發生的地方.
- 呼叫堆疊: 程式碼執行時堆疊幀的位置.(是一種資料結構,記錄了程式的基本位置.先進後出)
function multiply(x, y) {
return x * y;
}
function printSquare(x) {
var s = multiply(x, x);
console.log(s);
}
printSquare(5);
複製程式碼
當引擎開始執行此程式碼時,呼叫堆疊將為空。之後,步驟如下
併發和事件迴圈
JavaScript是一門單執行緒語言.因此只有一個單一的呼叫堆疊,並且一次只能做一件事,當我們進行一些複雜的耗時操作(圖形轉換)時.瀏覽器就無法進行其他事情,無法渲染任何內容.也不能執行其它程式碼.
為了解決瀏覽器被阻塞的問題,JavaScript提供了一種解決方案非同步回撥函式(asynchronous callback functions).非同步函式在解析過程中不會被立即執行,會被瀏覽器放入Task Queue
Task Queue 分為 Macrotask, Microtask
Event Loop 每執行一次 先從Macrotask佇列中拉出一個.然後檢查microtask佇列是否為空.依次執行直至清空佇列.
Macrotask主要包含:setTimeout、setInterval、setImmediate、I/O、UI互動事件
microtask主要包含:Promise、process.nextTick、MutaionObserver
process.nextTick 永遠大於 promise.then.
Node中,_tickCallback在每一次執行完TaskQueue中的一個任務後被呼叫,而這個_tickCallback中實質上幹了兩件事:
-
nextTickQueue中所有任務執行掉(長度最大1e4,Node版本v6.9.1)
-
第一步執行完後執行_runMicrotasks函式,執行microtask中的部分(promise.then註冊的回撥)
自測
console.log('1');
process.nextTick(function() {
console.log('4');
});
setTimeout(function() {
console.log('6');
process.nextTick(function() {
console.log('7');
});
}, 0);
new Promise(function(resolve, reject) {
console.log('2');
resolve();
}).then(function() {
console.log('5');
});
console.log('3');
複製程式碼
setTimeout(() => {
console.log(2)
}, 2)
setTimeout(() => {
console.log(1)
}, 1)
setTimeout(() => {
console.log(0)
}, 0)
// 谷歌瀏覽器環境中的執行順序是1 0 2。
// Node環境中的執行順序是隨機的
複製程式碼
What is the JavaScript event loop?
How JavaScript works: an overview of the engine, the runtime, and the call stack