淺析setTimeout與Promise

我們先看一到常見的前端面試題:

var p1 = new Promise(function(resolve, reject){
    resolve(1);
})
setTimeout(function(){
  console.log("will be executed at the top of the next Event Loop");
},0)
p1.then(function(value){
  console.log("p1 fulfilled");
})
setTimeout(function(){
  console.log("will be executed at the bottom of the next Event Loop");
},0)

上例代碼執行輸出順序如何?這道題也是本文創作的源泉,其答案是:

p1 fulfilled
will be executed at the top of the next Event Loop
will be executed at the bottom of the next Event Loop

異步任務



回顧JavaScript事件循環併發模型,我們瞭解了setTimeout和Promise調用的都是異步任務,這一點是它們共同之處,也即都是通過任務隊列進行管理/調度。那麼它們有什麼區別嗎?下文繼續介紹。

任務隊列

前文已經介紹了任務隊列的基礎內容和機制,可選擇查看,本文對任務隊列進行拓展介紹。JavaScript通過任務隊列管理所有異步任務,而任務隊列還可以細分爲MacroTask Queue和MicoTask Queue兩類。

MacroTask Queue

MacroTask Queue(宏任務隊列)主要包括setTimeout,setInterval, setImmediate, requestAnimationFrame, NodeJS中的`I/O等。

MicroTask Queue

MicroTask Queue(微任務隊列)主要包括兩類:

獨立回調microTask:如Promise,其成功/失敗回調函數相互獨立;
複合回調microTask:如 Object.observe, MutationObserverNodeJs中的 process.nextTick ,不同狀態回調在同一函數體;

MacroTask和MicroTask

JavaScript將異步任務分爲MacroTask和MicroTask,那麼它們區別何在呢?

依次執行同步代碼直至執行完畢;
檢查MacroTask 隊列,若有觸發的異步任務,則取第一個並調用其事件處理函數,然後跳至第三步,若沒有需處理的異步任務,則直接跳至第三步;
檢查MicroTask隊列,然後執行所有已觸發的異步任務,依次執行事件處理函數,直至執行完畢,然後跳至第二步,若沒有需處理的異步任務中,則直接返回第二步,依次執行後續步驟;
最後返回第二步,繼續檢查MacroTask隊列,依次執行後續步驟;
如此往復,若所有異步任務處理完成,則結束;

鏈接:https://juejin.im/post/5b7057b251882561381e69bf

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章