JavaScript 的 event loop - 非同步callback實際上發生了甚麼?

 JavaScript特性 - 同步性程式語言

JS其實是種同步性程式語言,和其他程式語言不同,JS在執行時是照順序一次只做一件事。在程式執行時,按照順序把程式碼push進stack區執行,執行完畢pop off出stack區,再把下一行程式碼push進stack區執行,直到完成整份文件。

所以當某一行程式碼卡在stack區處理不完的時候,程式執行變得緩慢(後面的程式碼排隊等著)或是卡死(while無限迴圈永遠執行不完)或是直接報錯(堆疊超過系統設定上限,系統直接說不幹了 XD)。所以在寫程式時檢查程式碼有沒有不小心無限迴圈很重要,學習優化程式碼提高程式運行效率的概念也要建立起來。


Callback function

Callback function其實就是把函式當作另一個函式的參數,透過另一個函式來呼叫它。當callback同步時,stack區會往上推疊callback function,再由上往下一件一件處理完移出stack區域;那當callback非同步呢?像是AJAX、Event Listener、setTimeOut、...等用法都讓callback function成為非同步。


非同步callback function發生甚麼事?

以經典的windows.setTimeOut( function() {...}, 毫秒)為例。

程式碼的指令:"在經過了多少毫秒後呼叫callback function"。但在實際上當程式執行到windows.setTimeOut( function() {...}, 毫秒)時,理所當然地把這包指令整包丟到stack區,要處理時發現了非同步指令,接著整包指令又被從stack區移除並被丟進webapis區解析要做的動作。

stack區在移除了setTimeOut指令後,繼續把下一行程式碼丟進stack區處理,而webapis區在處理完非同步指令的request後(setTimeOut為例,指令request是等待多少毫秒)把callback function丟進task queue等待,stack區清空後才依序把task queue裡pending的function丟進stack區處理。

有時候會發生:"奇怪?不是設定0秒後執行,為什麼延遲了?"的狀況。這就是因為callback function在被送進webapis區時,stack區開始執行下一段程式碼,而當callback function在task queue時stack區還未被清空,所以callback function默默地等默默的pending在那直到stack區空了才被移進去執行。這也就是event loop的功能,有效的讓JS這種單線程的程式語言達到非同步的效果。

留言

這個網誌中的熱門文章

我要轉職軟體工程師!- 門口徘徊撞牆期

Javascript、HTML、CSS我來了![Alpha Camp學期一] 新新手入門