前言
衆所周知,js是單線程的,就像我們不能一邊刷牙一邊洗臉(或許有些大佬真的可以),那麼單線程如何才能規劃調度好要做的任務呢?
這個時候就要介紹一下這個任務機制了~
任務種類
- 宏任務
- 微任務
注意:瀏覽器環境和node環境是不一樣的,本文只討論瀏覽器環境
規則
執行一個宏任務(先執行同步代碼)-->執行所有微任務-->UI render-->執行下一個宏任務-->執行所有微任務-->UI render-->
根據HTML Standard,一輪事件循環執行結束之後,下輪事件循環執行之前開始進行UI render。即:macro-task任務執行完畢,接着執行完所有的micro-task任務後,此時本輪循環結束,開始執行UI render。UI render完畢之後接着下一輪循環。但是UI render不一定會執行,因爲需要考慮ui渲染消耗的性能已經有沒有ui變動
需要注意的是,微任務是有優先級的,就如同上面的表格從上往下一樣,nextTick>Promise>MutationObserver.
- 那麼宏任務有沒有優先級呢??
大部分瀏覽器會把DOM事件回調優先處理 因爲要提升用戶體驗 給用戶反饋,其次是network IO操作的回調,再然後是UIrender,之後的順序就難以捉摸了,其實不同瀏覽器的表現也不太一樣,這裏不做過多討論。
來道經典題目
console.log('script start');
setTimeout(function() {
console.log('setTimeout');
}, 0);
Promise.resolve().then(function() {
console.log('promise1');
}).then(function() {
console.log('promise2');
});
console.log('script end');
答案是
'script start'、'script end'、'promise1'、'promise2'、'setTimeout'
先走完所有同步代碼-到promise微任務-宏任務setTimeout