# 2.5 Event loop

### 單線程（single threaded） <a href="#dan-xian-cheng-singlethreaded" id="dan-xian-cheng-singlethreaded"></a>

首先，我們要知道 JavaScript 是單線程（single threaded runtime）的程式語言，所有的程式碼片段都會在堆疊中（stack）被執行，而且**一次只會執行一個程式碼片段**（one thing at a time）。

### 堆疊（stack） <a href="#dui-die-stack" id="dui-die-stack"></a>

在 JavaScript 中的執行堆疊（called stack）會記錄目前執行到程式的哪個部分，如果進入了某一個函式（step into），便把這個函式添加到堆疊（stack）當中的最上方；如果在函式中執行了 return ，則會將此函式從堆疊（stack）的最上方中抽離（pop off）。

以下面的程式碼為例：

```
function b() {
}

function a() {
  b()
}

a()
```

當我們在執行 JavaScript 的函式時，首先進入 stack 的會是這個檔案中全域執行環境的程式；接著 a 會被呼叫（invoke）因此進入堆疊（stack）的最上方；在 a 中會呼叫 b( ) 因此 b( ) 會進入堆疊（stack）的最上方。

### JavaScript如何執行非同步事件（asynchronous callback）

1. 首先判斷JS是同步還是異步，同步就進入主線程運行，異步就進入event table
2. 異步任務在event table中註冊事件，當滿足觸發條件後（觸發條件可能是延時也可能是ajax回調），被推入event queue
3. 同步任務進入主線程後一直執行，直到主線程空閒時，才會去event queue中查看是否有可執行的異步任務，如果有就推入主線程中

```
/*Copy from JavaScript: Understanding the weird part*/
function waitThreeSeconds(){
 var ms = 3000 + new Date().getTime();
 while(new Date() < ms){}
 console.log("finished function");
}

function clickHandler(){
 console.log("click event!");
}

document.addEventListener('click', clickHandler);
console.log("started execution");
waitThreeSeconds();
console.log("finished execution");
```

![](https://2919068548-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Lh-g1QkhJbS3wly_4sc%2F-LnQ5N1-UvLPSFAAfVgt%2F-LnQ5uf0KVoM3i7sZdOO%2Fezgif.com-add-text.gif?alt=media\&token=7083cd56-ef28-4a7b-85cf-57c98881b1bf)

**event loop 的作用是去監控堆疊（call stack）和工作佇列（task queue），當堆疊當中沒有執行項目的時候，便把佇列中的內容拉到堆疊中去執行。**
