JS事件循環

一、JS 單線程執行

二、定時器函數詳解

        1、setTimeout()接受兩個參數,第一個是回調函數,第二個是推遲執行的毫秒數。

        setTimeout(fn,0)的含義是,指定某個任務在主線程最早可得的空閒時間執行,也就是說,儘可能早得執行。它在"任務隊列"的尾部添加一個事件,因此要等到同步任務和"任務隊列"現有的事件都處理完,纔會得到執行

        2、setInterval()

        setTimeout()只是將事件插入了"任務隊列",必須等到當前代碼(執行棧)執行完,主線程纔會去執行它指定的回調函數。要是當前代碼耗時很長,有可能要等很久,所以並沒有辦法保證,回調函數一定會在setTimeout()指定的時間執行。

        3、process.nextTick()

        process.nextTick方法可以在當前"執行棧"的尾部----下一次Event Loop(主線程讀取"任務隊列")之前----觸發回調函數。也就是說,它指定的任務總是發生在所有異步任務之前。

        4、setImmediate()

        setImmediate方法則是在當前"任務隊列"的尾部添加事件,也就是說,它指定的任務總是在下一次Event Loop時執行,這與setTimeout(fn, 0)很像。

三、任務隊列執行邏輯

一下均參考自https://juejin.im/post/5a63470bf265da3e2c383068

        

四、案例

        


        解析:

我們代碼的開始執行都是從script(全局任務)開始,這個全局任務屬於宏任務;代碼由上向下執行;

  1. 第1行,遇到了一個timer異步任務,屬於宏任務,放入宏任務隊列;

  2. 第8行,遇到log,內部沒有其它函數,直接輸出main1;

  3. 第10行,函數的定義,不執行;

  4. 第17行,遇到new Promise(),進入回調函數內部:

    1) 遇到promise.nextTick,屬於微任務,放入微任務隊列nextTick3;

    2) 遇到log,內部沒有其它函數,直接輸出promise 1;

    3) 遇到resolve回調,屬於微任務,放入微任務隊列promise then;

  5. 第27行,遇到log,內部沒有其它函數,直接輸出main2;

  6. 第29行,遇到promise.nextTick,屬於微任務,放入微任務隊列nextTick4;

  7. 第33行,執行say():

    1)遇到log,內部沒有其它函數,直接輸出hello;

    2)遇到promise.nextTick,屬於微任務,放入微任務隊列nextTick2;

    到此爲止,我們已經做了如下事情:

    1)宏任務隊列中放入了一個timer函數;

    2)輸出了main1promise 1main2hello1

    3)微任務隊列中已經放入了promise then,nextTick3,nextTick4,nextTick2;

此時,我們的全局任務已執行完成了,就要馬上執行完整個微任務隊列。但是在微任務中,process.nextTick 是一個特殊的任務,它會被直接插入到微任務的隊首(當然了,多個process.nextTick 之間也是先入先出的),優先級最高。所以,依次輸出nextTick3,nextTick4,nextTick2,promise then

  1. 這時,執行棧爲空了,可是別忘了,我們的宏任務隊列還放者一個timer函數待執行,進入timer函數:

    1)遇到log,內部沒有其它函數,直接輸出setTimeout;

    2)遇到promise.nextTick,屬於微任務,放入微任務隊列nextTick1;

  2. 這個timer宏任務也執行完了,就馬上執行完整個微任務隊列,微任務隊列目前只有一個任務,直接輸出nextTick1

  3. 這時,執行棧又爲空了,還有其它任務嗎? 沒有了,大功告成;

以上的這種當函數執行棧爲空,從任務隊列中去一個任務來執行。再次爲空,再取一個任務來執行,如此循環,這就是Event Loop,事件循環機制;

參考:

JavaScript 運行機制詳解:再談Event Loop:(http://www.ruanyifeng.com/blog/2014/10/event-loop.html)

淺析nodejs事件循環機制:(https://juejin.im/post/5a63470bf265da3e2c383068)




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章