瀏覽器的微任務MicroTask和宏任務MacroTask

簡介

​ 我把JavaScript在瀏覽器中運行主要分爲如下幾種類型的任務:javascript

  • 同步任務(MainTask) :同步任務是指JavaScript按照正常順序執行的代碼,好比:函數調用,數值運算等等,只要是執行後當即可以獲得結果的就是同步任務。
  • 宏任務 (MacroTask):setTimeout、setInterval、I/O、UI渲染
  • 微任務 (MicroTask) :Promise、Object.obsever、MutationObsever
  • 用戶交互事件(User Interaction Event):點擊事件onclick、鍵盤事件onkeywodn、鼠標事件onmouseover等等

執行順序

img

具體流程:html

  1. 執行完主邏輯中的同步任務
  2. 取出微任務隊列(MicroTask Queue)中的任務執行,直到隊列被徹底清空
  3. 取出宏任務隊列(MacroTask Queue)中的一個任務執行。
  4. 取出微任務隊列(MicroTask Queue)中的任務執行,直到隊列被徹底清空
  5. 重複 3 和 4,直到宏任務隊列(MacroTask Queue)被清空。

img

demo1:宏任務(MacroTask)和微任務(MicroTask)執行順序

demo1.htmljava

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>demo1:宏任務(MacroTask)和微任務(MicroTask)執行順序</title>
</head>
<body>
    <script type="text/javascript">
        console.log('同步任務1 start');
        setTimeout(function () {
            console.log('宏任務1:setTimeout...');
        }, 0);
        Promise.resolve().then(function () {
            console.log('微任務1 Promise.then() 1')
        }).then(function () {
            console.log('微任務2 Promise.then() 2')
        });
        setTimeout(function () {
            console.log('宏任務2:setTimeout...');
            Promise.resolve().then(function () {
                console.log('宏任務2:setTimeout => 微任務 Promise.then()')
            });
        }, 0);
        setTimeout(function () {
            console.log('宏任務3:setTimeout...');
        }, 0);
        Promise.resolve().then(function () {
            console.log('微任務3 Promise.then() 1')
        }).then(function () {
            console.log('微任務3 Promise.then() 2')
        })
        console.log('同步任務2 end');
    </script>
</body>
</html>

運行結果:git

img

以上代碼詳細的運行步驟隊列圖,我已經寫成了PPT,你們能夠下載打開看效果,能夠詳細瞭解每一段代碼在隊列中的樣子:github

https://github.com/Jameswain/...segmentfault

demo2:setInterval —— setTimeout的語法糖

​ setInterval其實能夠說是setTimeout的語法糖,由於setInterval可以實現的功能,setTimeout也能實現,下面經過一個小例子實現使用setTimeout實現setInterval的定時調度功能:瀏覽器

function logic() {
    console.log(Date.now());
    setTimeout(logic, 1000);
}
logic();

demo3:setInterval宏任務和微任務深刻

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>demo1:setTimeout與setInterval</title>
</head>
<body>
    <div class="demo">demo</div>
    <script type="text/javascript">
        console.log('同步任務1 start');
        setInterval(() => {
            console.log('宏任務1:setInterval...');
            Promise.resolve().then(function () {
                console.log('宏任務1:setInterval => 微任務1 Promise.then()')
            });
            Promise.resolve().then(function () {
                console.log('宏任務1:setInterval => 微任務2 Promise.then()')
            });
            Promise.resolve().then(function () {
                console.log('宏任務1:setInterval => 微任務3 Promise.then()')
            });
        }, 3000);
        setTimeout(function () {
            console.log('宏任務2:setTimeout...');
        }, 0);
        // 微任務:監聽DOM屬性變化,當屬性發生變化時觸發回調函數
        const demo = document.querySelector('.demo');
        new MutationObserver(() => {
            console.log('MutationObserver Callback...');
        }).observe(demo, { attributes: true });

        Promise.resolve().then(function () {
            console.log('微任務1 Promise.then() 1')
            Promise.resolve().then(() => {
                console.log('微任務1-1 Promise.then() 1')
            });
            Promise.resolve().then(() => {
                console.log('微任務1-2 Promise.then() 2')
                Promise.resolve().then(() => {
                    console.log('微任務1-2-1 Promise.then() 1')
                });
            });
        });
        // 修改DOM元素屬性,將回調變化回調函數放入微任務隊列中
        demo.setAttribute('data-random', Math.random());
        console.log('同步任務2 end');
    </script>
</body>
</html>

運行結果:dom

img

​ 從運行結果能夠發現,JavaScript的代碼在瀏覽器中的執行順序是【同步任務】 => 【清空微任務隊列】=>【宏任務】=> 【清空微任務隊列】,若是在執行微任務時,又發現了微任務,它會把這個微任務放入到微任務隊列的末尾。宏任務也同樣,若是在執行宏任務的時候發現了宏任務,它也會把這個宏任務放入宏任務隊列的末尾。函數

​ 上代碼詳細的運行步驟隊列圖,我已經寫成了PPT,你們能夠下載打開看效果,能夠詳細瞭解每一段代碼在隊列中的樣子:oop

https://github.com/Jameswain/...

參考文檔:

Tasks, microtasks, queues 和 schedules

Tasks, microtasks, queues and schedules

瀏覽器和Node不一樣的事件循環(Event Loop)

相關文章
相關標籤/搜索