1. 程式人生 > >js事件迴圈機制(二)

js事件迴圈機制(二)

前言

上一篇介紹了 事件迴圈 的基礎, 這一篇主要介紹 macrotaskmicrotask

一、引入

    (function test() {
        setTimeout(function() {console.log(4)}, 0);
        new Promise(function executor(resolve) {
            console.log(1);
            for( var i=0 ; i<10000 ; i++ ) {
                i == 9999 && resolve();
            }
            console.log(2
); }).then(function() { console.log(5); }); console.log(3); })()

執行結果

    1
    2
    3
    5
    4

可以看看whatwg規範,大概可以用下面的事件執行模型來理解

二、event-loop 執行模型

  • 1.在 macrotask 佇列中執行最早的那個 task ,然後移出

  • 2.執行 microtask 佇列中所有可用的任務,然後移出

  • 3.執行下一個 macrotask 中的任務 (再跳到第2步)

三、macrotask microtask分類

macrotask: 整段script程式碼 setTimeout setInterval setImmediate I/O UI渲染

microtask: Promise process.nextTick Object.observe MutationObserver

按照上面的事件執行模型和事件分類,來理解一下上面的demo

    //虛擬碼
    var macrotasks = ['整段script程式碼'],
        microtasks = [];
    //一次事件迴圈
    while( macrotasks.length>0){
        macrotasks.shift();
        // 有些macrotask 可能會產生macrotask microtasks
// 即 microtasks.push() // 如上面的 '整段程式碼' 產生一個macrotask -> setTimeout,又產生一個microtask -> Promise while(microtasks.length>0){ microtasks.shift(); } }

上面的demo執行過程如下:開始時 macrotask佇列 有 ‘整段的script程式碼’,microtask佇列無任務。
開始執行第一個 macrotask:
- 1.發現 setTimeout ,執行 macrotasks.push("setTimeout")
- 2.發現 Promise執行console.log(1),執行 microtasks.push('Promise')
,執行console.log(2)
- 3.執行console.log(3);

至此 第一個 macrotask 處理完成,檢查是否有 microtask,開始處理 microtask:
- 1.執行console.log(5);

至此 microtask 處理完成,檢查是否還有 macrotask,開始處理第二個 macrotask:
- 1.執行 console.log(4)

四、參考文章