簡單易懂的宏任務和微任務執行順序
背景
很多朋友在寫面試題:宏任務與微任務的執行時機時,容易犯迷糊。之前我也寫過兩篇文章,這次加上詳細的講解,讓大家更容易理解
什麼是宏任務、微任務?
- 首先要稱得上是宏任務、微任務的,必須是一個回調函數,例如:
setTimeout(getList,5000);
這個getList
就是一個回調函數
-
必須是異步執行的回調函數
-
區分宏任務與微任務
宏任務
:
渲染事件(如解析 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 循環模式
-
接着讀取全局同步代碼對應的微任務隊列並且執行完畢
-
再繼續執行此時需要執行的宏任務,例如:到時間需要執行的定時器回調函數等
-
執行完宏任務後,繼續執行對應的微任務隊列,清空微任務隊列
-
接着繼續執行此時需要執行的宏任務...
週而復始,像一個 for 循環一樣。
用一張圖來講解就是:
以上就是微任務和宏任務的執行機制
以上便是本次分享的全部內容,希望對你有所幫助 ^_^
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/9o8kiLVaBIAQKSYZMRJg_Q