說到宏任務和微任務,我們就不得不提 Event Loop 了
JS的本質是單線:
1. 一般來說,非阻塞性的任務采取同步的方式,直接在主線程的執行棧完成。
2. 一般來說,阻塞性的任務都會采用異步來執行,異步的工作一般會交給其他線程完成,然后回調函數會放到事件隊列中。
當主線程的任務執行完了(執行棧空了),JS會去詢問事件隊列
執行一個宏任務(先執行同步代碼)-->執行所有微任務-->UI render-->執行下一個宏任務-->執行所有微任務-->UI render-->......
根據HTML Standard,一輪事件循環執行結束之后,下輪事件循環執行之前開始進行UI render。即:macro-task任務執行完畢,接着執行完所有的micro-task任務后,此時本輪循環結束,開始執行UI render。UI render完畢之后接着下一輪循環。但是UI render不一定會執行,因為需要考慮ui渲染消耗的性能已經有沒有ui變動
哪些是宏任務、微任務呢?
推薦閱讀:https://juejin.im/post/5b73d7a6518825610072b42b
宏任務macrotask:主代碼塊 > setImmediate > MessageChannel > setTimeout / setInterval (大部分瀏覽器會把DOM事件回調優先處理 因為要提升用戶體驗 給用戶反饋,其次是network IO操作的回調,再然后是UIrender,之后的順序就難以捉摸了,其實不同瀏覽器的表現也不太一樣,這里不做過多討論。)
微任務microtask:process.nextTick > Promise = MutationObserver
就是說任務執行的順序是建立與優先級之上的:
如果隊列已經有一個setTImeout的宏任務,后來又加入了主代碼的宏任務,會讓主代碼的的任務插隊。