簡單易懂的宏任務和微任務執行順序

背景

很多朋友在寫面試題:宏任務與微任務的執行時機時,容易犯迷糊。之前我也寫過兩篇文章,這次加上詳細的講解,讓大家更容易理解

什麼是宏任務、微任務?

  1. 首先要稱得上是宏任務、微任務的,必須是一個回調函數,例如:
setTimeout(getList,5000);

這個getList就是一個回調函數

  1. 必須是異步執行的回調函數

  2. 區分宏任務與微任務

宏任務:

渲染事件(如解析 DOM、計算佈局、繪製);

用戶交互事件(如鼠標點擊、滾動頁面、放大縮小等);

JavaScript 腳本執行事件;

網絡請求完成、文件讀寫完成事件

微任務:

MutationObserver;

Promise.resolve();

就這麼些任務,在瀏覽器環境中,系統已經把他們區分成了宏任務和微任務,並沒有其他特殊的含義!!死記下來就行了


每個宏任務對應了一個微任務隊列

每一個宏任務,都對應了一個微任務隊列,沒什麼特別的,你現在知道了這點,而且知道了哪些是宏任務和微任務

全局同步代碼,是特殊的宏任務

全局的同步執行代碼,也要看成一個宏任務,那這個宏任務,也對應了他的微任務隊列,例如:

for (let i=0;i<1000;i++){

//dosomething

}
Promise.resolve().then(()=>{
  //dosomething
})

setTimeout(()=>{
  //dosomething
})

當 for 循環(全局的同步代碼執行完畢後,就會開始執行微任務隊列的任務),這個時候就會去執行Promise.resolve().then裏面的代碼。

當全局同步代碼這個宏任務對應的微任務隊列執行完畢以後,就會去繼續執行宏任務。

那麼接下來,就會執行setTImeout回調裏面的代碼

假設宏任務裏面再繼續有微任務

for (let i=0;i<1000;i++){

//dosomething

}
Promise.resolve().then(()=>{
  console.log(1);
})

setTimeout(()=>{
  console.log(2);
  setTimeout(()=>{
   console.log(3);
  })
  Promise.resolve().then(()=>{
  console.log(4);
})
})

打印順序是:1 2 4 3

分析:

當全局的同步代碼(宏任務)執行完畢後,執行全局宏任務對應的微任務隊列,輸出 1.

清空全局同步代碼對應的微任務隊列後,開始執行下一個宏任務,下一個宏任務是定時器回調函數,輸出 2.

這個定時器宏任務對應了一個微任務隊列,此時執行 Promise.resolve.then 這個微任務,輸出 4

最後執行完這個微任務隊列後,繼續執行下一個宏任務,輸出 3


加餐

大家看完上面,可能只知道了宏任務和微任務的執行時機,但是整個系統是怎麼任務調度的?

其實大家可以把整個頁面任務調度系統看成是一個 for 循環

整個系統的任務調度

週而復始,像一個 for 循環一樣。

用一張圖來講解就是:

以上就是微任務和宏任務的執行機制

以上便是本次分享的全部內容,希望對你有所幫助 ^_^

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/9o8kiLVaBIAQKSYZMRJg_Q