JavaScript 的事件機制

JavaScript 的事件機制

關於Event Loop,查閱多篇博客,或多或少總有些出入,在此寫下本身關於Event Loop的理解

按同步與異步分

  • 首先判斷JS是同步仍是異步,同步就進入主進程,異步就進入event table
  • 異步任務在event table中註冊函數,當知足觸發條件後,被推入event queue
  • 同步任務進入主線程後一直執行,直到主線程空閒時,纔會去event queue中查看是否有可執行的異步任務,若是有就推入主進程中

按宏任務與微任務分 (更準確)

  • macro-task(宏任務):包括總體代碼script,setTimeout,setInterval,setImmediate, I/O, UI rendering
  • micro-task(微任務):Promise.then,process.nextTick
許多地方把Promise標記爲微任務,可是這容易讓人誤覺得new Promise的時候這個過程是個微任務。實際上是Promsie.then、Promise.catch是微任務,new Promise的時候當作普通的生成對象來看待,因此在此我標記爲Promise.then
  • 執行本輪個宏任務html

    • 過程當中若是遇到微任務,是同步任務就將其放到微任務的[事件隊列]裏,異步放入微任務[事件表]中,註冊函數,達到執行條件,推入微任務[事件隊列]中 (目前爲止我還不知道微任務有沒有異步任務)
    • 遇到宏任務,是同步任務就將其放到宏任務的[事件隊列]裏,異步放入宏任務[事件表]中,註冊函數,達到執行條件,推入宏任務[事件隊列]中
  • 本輪宏任務執行完,查看微任務的[事件隊列],並將裏面所有的微任務依次執行完,從宏任務[事件隊列]中執行下一輪宏任務

相關知識

  • JS單線程,這線程中只有一個惟一的事件循環
  • 一個線程中,事件循環是惟一的,可是能夠有多個任務隊列(微任務隊列只有一個)
  • 任務隊列分宏任務隊列與微任務隊列
那麼問題來了,多個宏任務隊列時,下一趟的宏任務該取哪一個呢?上述方法中,我是將宏任務都當作一個隊列的

Examples

/* example1 */
setTimeout(function () {
    console.log(1);
},7);

new Promise(function (resolve) {
    console.log(2);
    for (var i = 0; i < 10000; i++) {
        i == 99 && resolve();
    }
}).then(function () {
    console.log(3);
    setTimeout(() => {
        console.log(4);
    });
})

console.log(5);
// 2 3 5 (4 1) 後兩個數字的順序與兩定時器的delayTime有關,誰先知足觸發條件就先輸出誰 (html5 標準中,規定delayTime >= 4ms)

/* example2 */
setTimeout(_ => console.log(4));

new Promise(resolve => {
    resolve()
    console.log(1)
}).then(_ => {
    console.log(3)
    Promise.resolve().then(_ => {
        console.log('before timeout')
    }).then(_ => {
        Promise.resolve().then(_ => {
            console.log('also before timeout')
        })
    })
})

console.log(2);
// 這個也不難,分析分析就出結果了

finally

綜上 菜雞二問前端

  • 微任務事件隊列中存在異步任務嘛?
  • 多個宏任務事件隊列,下一輪宏任務時該從哪一個宏任務事件隊列中取?
這些問題都需在不斷的深刻了解中才能知道答案
以上就是閱讀多篇博客以後我的對Event Loop的一些看法,或有不正確之處,望批評指正

參考
前端基礎進階(十二):深刻核心,詳解事件循環機制
10分鐘理解JS引擎的執行機制html5

相關文章
相關標籤/搜索