瞭解js的巨集任務(macrotask)和微任務(microtask)以及Event-Loop
JavaScript
首先,JavaScript是一個單執行緒的指令碼語言,所以就是說在一行程式碼執行的過程中,必然不會存在同時執行的另一行程式碼,就像使用alert()後進行列印,如果不關閉彈窗,則不會執行後續的列印操作
微任務與巨集任務的區別
巨集任務:
類似於去銀行辦理業務,櫃員同一時間只能為一個客戶辦理業務,因此每個客戶要想辦理業務就必須進行排隊領號,這裡的“客戶”=巨集任務,當櫃員處理完當前客戶的所有問題後,就會接待下一位客戶,廣播報號時也就意味著下一個巨集任務的開始。多個巨集任務的時候就是相當於排隊的客戶們。
常見巨集任務:
# | 瀏覽器 | Node |
setTimeout | √ | √ |
setInterval | √ | √ |
setImmediate | x | √ |
requestAnimationFrame | √ | x |
任務佇列中的都是已經完成的非同步操作,而不是說註冊一個非同步任務就會被放在任務佇列中,就像銀行排隊叫號的時候你不在,那麼就需要重新領號,櫃員會直接進行下一位客戶的業務處理,也就是直接進入下一個巨集任務了
微任務:
在一個巨集任務執行的過程中,是可以新增微任務的,類似於櫃員處理當前客戶的時候,客戶手頭不止一個需求需要得到處理,有可能有多個業務需要辦理,而裡面的多個業務指的就是微任務,直到當前巨集任務中的微任務辦理結束後才會進行下一個巨集任務
常見微任務:
# | 瀏覽器 | Node |
process.nextTick | x | √ |
MutationObserver | √ | x |
Promise.then catch finally | √ | √ |
舉例:
setTimeout(() => { //執行後 回撥一個巨集事件 console.log('內層巨集事件3') }, 0) console.log('外層巨集事件1'); new Promise((resolve) => { console.log('外層巨集事件2'); resolve() }).then(() => { console.log('微事件1'); }).then(()=>{ console.log('微事件2') })
列印結果
//外層巨集事件1 //外層巨集事件2 //微事件1 //微事件2 //內層巨集事件3
• 首先瀏覽器執行js進入第一個巨集任務進入主執行緒, 遇到setTimeout分發到巨集任務Event Queue中
• 遇到console.log()直接執行 輸出 外層巨集事件1
• 遇到Promise, newPromise直接執行 輸出 外層巨集事件2
• 執行then被分發到微任務Event Queue中
•第一輪巨集任務執行結束,開始執行微任務 列印 '微事件1' '微事件2'
•第一輪微任務執行完畢,執行第二輪巨集事件,列印setTimeout裡面內容'內層巨集事件3'
Event-Loop(只簡單說一下)
正因為js是一個單程序的語言,同一時間不能處理多個任務,所以何時執行巨集任務、微任務,我們就需要一個可以進行判斷邏輯的存在
每次辦理完一個業務,會詢問當前客戶是否還需要辦理其他業務(檢查還有沒微任務需要處理)
客戶明確告知沒有業務需要辦理了,櫃員會去檢視後面是否還有客戶需要辦理業務(結束本次巨集任務後,檢查還有沒有未處理的巨集任務)
這個檢查的過程是持續進行的,每完成一個任務都會進行一次,而這樣的操作就被稱為Event Loop
。
以及還要明確的是,Event Loop
只是負責告訴你該執行那些任務,或者說哪些回撥被觸發了,真正的邏輯還是在程序中執行的。