JS的同步非同步與Event Loop

同步非同步

有些人會說 JavaScript 是非同步的語言

不過要精確點說的話
JS 是一個 Single Thread(單執行緒)語言,一次只會做一件事,
所以 JS 本身是同步的語言,只是它具有非同步的特性

這是為了符合瀏覽器的使用情境,JS 需要具有非同步的能力,而要達到非同步,靠的就是 Event Loop

Event Loop 運行機制

在 JS 執行緒中,有 Heap 和 Stack,Heap 是處理記憶體分配的地方,
而在 Stack 中,就是所有的 JS 任務,每個任務執行完後就會彈出 Stack。

流程是,JS 執行緒會逐一執行 Stack 內的程式,當遇到非同步行為時(例如 setTimeout),它就會把它推到 Event Queue(就是上圖中的 Callback Queue)裡,然後等 Stack 裡的程式都跑完 清空了,就會開始逐一執行 Event Queue 中的任務,Queue 是先進先出的資料結構,所以先進來的函式會先被執行。

這個過程是不斷循環的,所以這機制又稱為 Event Loop。

範例動畫流程

動畫取自 JavaScript Visualized: Event Loop

  1. greet 函式被調用,return ‘Hello!’,彈出 Stack;
    respond 函式被調用,return 一個 setTimeout
  2. 由於 respond 函式 return 了一個非同步行為(setTimeout),所以會把 setTimeout 轉交給 Web Api 處理,接著 respond()彈出 Stack
  3. 設定的 1 秒到了,添加到 Event Queue 裡
  4. 如果 Stack 為空,那麼 Event Queue 中的第一項將被添加到 Stack
  5. 在 Stack 中 return ‘Hey’,彈出 Stack

簡單題目測試

這段程式輸出的結果是?

function test(){

  console.log('a')

  setTimeout(() => {
    console.log('b')
  }, 0)

  console.log('c')
}

test()

答:
a
c
b

因為 b 是一個非同步事件,他會被放到 Event Queue 裡,
也就是說,它在所有程式執行完(Stack 清空)後才會執行,所以答案就是 a->c->b

Reference:
https://www.youtube.com/watch?v=8aGhZQkoFbQ
https://dev.to/lydiahallie/javascript-visualized-event-loop-3dif

Similar Posts