初識JavaScript EventLoop

gzc發表於2018-01-22

初識JavaScript EventLoop

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 EventLoop

併發和事件迴圈

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中實質上幹了兩件事:

  1. nextTickQueue中所有任務執行掉(長度最大1e4,Node版本v6.9.1)

  2. 第一步執行完後執行_runMicrotasks函式,執行microtask中的部分(promise.then註冊的回撥)

初識JavaScript EventLoop

自測

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