JavaScript 同步、非同步的處理

莊創偉
2 min readSep 7, 2018

一般對同步、非同步的認知是同步即為在主執行緒執行,非同步則是開另一個執行緒進行處理,兩邊各自獨自運作以避免耗時過長造成阻塞。

JS 同樣也有非同步的函數用來避免前端 UI 因執行過久而造成頁面被 LOCK

比如ajax、settimeout、各種event事件(click,onchange…)都是非同步事件

世界看似很美好....

但是~~~~

JS是單執行緒
JS是單執行緒
JS是單執行緒

既然是單執行緒那不論同步與非同步都是在同一個線程中做處理,JS 是如何處理非同步的需求來達成線程不阻塞呢?其實只是將非同步的程式丟到最後的最後再來處理而已。

JS 偵測到非同步需求,會將其放到queue中直到所有程式碼都跑完了,JS會再回頭到queue中按順序將function 拉回來處理。

假設在執行過程中插入一個0秒立刻執行的setTimeout

console.log(1)setTimeout(function(){
console.log(2)
},0)
console.log(3)-----輸出結果-------1
3
2

因為非同步程式會被放在最後在執行於是執行順序會變成這樣

console.log(1)console.log(3)console.log(2)

假設要寫一個隨著秒數印出1 2 3 4 5的程式,依直覺很容易寫成以下的樣子

for(i=1;i<=5;i++){setTimeout(function(){console.log(i)},i*1000)}

然而依循上面的邏輯非同步放到最後執行,結果會依秒數印出5個6
*等待迴圈跑完後才會執行setTimeout 註冊的5個function()

如果要正確依秒數跑出 1 2 3 4 5 可以使用遞迴呼叫。或者將 i 宣告為區域變數

for(let i=1;i<=5;i++){setTimeout(function(){console.log(i)},i*1000)}

宣告為 let 後,因為其作用域僅在for 迴圈內,所以function內的 i 不會被修改到

補充--關於ajax

js 處理 ajax 時會"立刻"呼叫”瀏覽器”進行連線訪問,並創建event(success,error等)等待ajax回應時可以觸發。然後依照同步或非同步設定判斷是否繼續往下執行或等待回應

參考資料

Event Loop

Loupe

--

--

莊創偉

學海無涯。但是為了生計還是得下海的風塵男子