在了解這三樣東西之前,要先知道 JavaScript 是單執行緒 single thread 的程式語言,因此一次只能執行一個任務,而 JavaScript中等待執行的任務會放入一個堆疊,我們叫它為 Call Stack。
以下是一個Call Stack的範例:
最終會依序印出:
foo
bar
baz
瀏覽器執行上述JavaScript時,Call Stack這個容器是怎麼被操作的呢,讓我們看看下圖詳細的流程吧!
簡單來說Callback Queue就是各種非同步事件用來排隊的地方,一般認為就是用以下幾種分出不同的佇列,但實作部份要視瀏覽器決定,其中的順序是依照FIFO(先進先出),以下是幾種會包含的任務:
Events(事件): EventTarget物件非同步分派到對應的Events物件
Parsing(解析): HTML parser
Callbacks(回調): 呼叫非同步回調函式
使用外部資源: 資料庫、檔案、Web I/O
DOM處理的反應: 回應DOM處理時的元素對應事件
在瀏覽器端的JavaScript程式語言中,除了一般的事件分派外,還有少數幾個內建的API與相關物件有類似的非同步機制,有一些簡單的樣式可以利用它們模擬出非同步的執行程式:
setTimeout
setInterval
XMLHttpRequest
requestAnimationFrame
WebSocket
Worker
某些HTML5 API,例如File API、Web Database API
有使用onload的API
舉個例子:
假如非同步事件會和同步事件都一起被放進 Call stack,那麼就會造成阻塞blocking,例如我們發出一個HTTP請求,那麼在完成 response 之前,就會因為 JavaScript 單執行緒的特性,我們在網頁上都無法進行其它操作。
為了避免這種問題,非同步事件裡的回調函式 callback function,它們會進入到 Callback Queue 裡面,等 Call stack 裡面沒有其它任務才會進入到 Call stack 執行。
上述提到非同步事件會等 Call stack 裡面沒有其它任務才會進入到 Call stack 執行,就是透過 Event loop 機制去做判斷的,其監測步驟如下:
最後,推薦讀者們可以觀看以下影片,講者Philip Roberts搭配了JavaScript運行的動畫講解Event Loop的機制,非常詳細且清楚!