iT邦幫忙

1

React 學習筆記_10(JavaScript 中的Event loop)

Event loop

想要理解同步與非同步可以觀看這個影片 : What the heck is the event loop anyway? | Philip Roberts | JSConf EU非常清楚的講解的同步與非同步。

Stock

在程式的執行裡有個東西叫做 "call stack" 負責記錄著每個function執行時所需要用到的資源並記錄著function執行的順序
Example :

function a()
{
    return 1;
}
function b()
{
    a();
}
function c()
{
    b();
}
c();

先呼叫的function C, C 裡面呼叫function b, b 裡面呼叫 function a
https://ithelp.ithome.com.tw/upload/images/20200324/20124767iaTXnxAkl4.png

錯誤 stack overflow

知名的錯誤stack overflow指的是stack太多東西滿出來了,例如連續呼叫一個function十萬次,stack沒辦法存放這麼多動作,就會丟出stack overflow錯誤。

thread

雖然JaveScrip只有一個"thread" 代表著一次只能做一件事,那怎麼進行非同步動作呢?雖然一個thread只能做一件事,但是卻可以有多個thread,以setTimeout function來說 :

setTimeout(fn,2000);  

當2秒後呼叫fu function,瀏覽器就會開啟另一個thread去計時,而main thread就可以往下執行下一個指令,當另一個thread計數好2秒後會將fn丟回main thread。
https://ithelp.ithome.com.tw/upload/images/20200324/20124767P6JPagklxL.png
(圖片來源 : Understanding Event Loop, Call Stack, Event & Job Queue in Javascript)

若執行了 "setTimeOut(fn,2000)"這一行程式,會先把setTimeout(fn,2000)放到stock中,由於setTimeout屬於Web API,所以會將這行程式丟到另一個thread去計數2秒,然後當計數結束後會將fn放到callback queue中,而當stack清空時(其他function執行完畢),callback queue會將計數完成的fn放回stack

callback queue : 不斷偵測stack是否為空,若是空的就把callback queue裡面的東西丟到stack中

以程式角度來說 :

while(1)
{
    if(callStack.length === 0 && callbackQueue.length > 0)
    {
        callStack.push(callbackQueue.dequeue()) // 拿出 callbackQueue ,並放到 callStack 
    }
}

舉一個影片中的範例 :

setTimeout(() => {
    console.log("0ms")
},0)
console.log("hello");

在這邊由於"setTimeout"會將計數放到另一個thread中進行計數,雖然計數的時間為0ms,但是由於進到另一個thread中,所以0ms計數完後會被放到callback queue中,而這個時候stack裡面擁有"console.log("hello")" (stack並非為空),所以callback queue會等待"console.log("hello")"執行結束後才會將callback queue中的"console.log("0ms")" 放入stack中並且執行,所以會先是hello先被console出來後,0ms才會被console出來。

Step 0 :
https://ithelp.ithome.com.tw/upload/images/20200324/20124767tRAPLtSATx.png

Step 1 : 將setTimeout放入stack中,之後將他放到Web API中計數
https://ithelp.ithome.com.tw/upload/images/20200324/20124767Bagszzj2lF.png

Step 2 : 將"console.log("hello")"放入stack,Web API中計數完成放入callback queue
https://ithelp.ithome.com.tw/upload/images/20200324/20124767I3NNiOAzZq.png
由於stack中還有動作(console.log("hello"))所以callback queue中的console.log("0ms")不會放到stack中。

Step 3 : Stack中為空,將callbakc queue中的console.log("0ms")放入stack並執行
https://ithelp.ithome.com.tw/upload/images/20200324/20124767a8vOAZ4WeI.png

參考資料 :
JavaScript 中的同步與非同步(上):先成為 callback 大師吧!


尚未有邦友留言

立即登入留言