異步執行順序

異步執行順序

任務隊列

JavaScript經過任務隊列管理全部異步任務,而任務隊列還能夠細分爲MacroTask Queue和MicoTask Queue兩類。html

MacroTask Queue

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

MicroTask Queue

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

1.獨立回調microTask:如Promise,其成功/失敗回調函數相互獨立;異步

2.複合回調microTask:如 Object.observe, MutationObserver 和NodeJs中的 process.nextTick ,不一樣狀態回調在同一函數體;async

MacroTask和MicroTask

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

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

promise、setTimeout、async的前後執行順序

準則:

1.先執行同步代碼,遇到異步代碼就先加入隊列,而後按入隊順序執行異步代碼,最後執行setTimeout隊列的代碼

2.setTimeout的任務隊列優先級低於promise隊列,setTimeout的隊列與promise不是一個隊列

3.setTimeout有默認4ms的延遲,因此不會當即執行,而是會進入宏隊列

4.await會讓出當前線程,將後面的代碼加到任務隊列中,而後繼續執行test()函數後面的同步代碼
複製代碼
async function async1() {           
                     console.log("async1 start");  //(2)        
                     await  async2();            
                     console.log("async1 end");   //(7)    
                 }        
                 async  function async2() {          
                     console.log( 'async2');   //(3)     
                 }       
                 console.log("script start");  //(1)      
                 setTimeout(function () {            
                     console.log("settimeout");  //(8)      
                 },0);        
                 async1();        
                 new Promise(function (resolve) {           
                     console.log("promise1");   //(4)         
                     resolve();        
                 }).then(function () {            
                     console.log("promise2");    //(6)    
                 });        
                 console.log('script end');//(5)
複製代碼
解析:
先按順序執行同步代碼  從‘script start‘開始,

執行到setTimeout函數時,將其回調函數加入隊列(此隊列與promise隊列不是同一個隊列,執行的優先級低於promise)。

而後調用async1()方法,await async2();//執行這一句後,輸出async2後,await會讓出當前線程,將後面的代碼加到任務隊列中,而後繼續執行test()函數後面的同步代碼

繼續執行建立promise對象裏面的代碼屬於同步代碼,promise的異步性體如今then與catch處,因此promise1被輸出,而後將then函數的代碼加入隊列,繼續執行同步代碼,輸出script end。至此同步代碼執行完畢。

開始從隊列中調取任務執行,因爲剛剛提到過,setTimeout的任務隊列優先級低於promise隊列,因此首先執行promise隊列的第一個任務,由於在async函數中有await表達式,會使async函數暫停執行,等待表達式中的 Promise 解析完成後繼續執行 async 函數並返回解決結果。

因此先執行then方法的部分,輸出promise2,而後執行async1中await後面的代碼,輸出async1 end。。最後promise隊列中任務執行完畢,再執行setTimeout的任務隊列,輸出settimeout。


setTimeout(fn,0)的含義是指某個任務在主線程最先可得的空閒時間執行。它在「任務隊列」的尾部添加一個事件,所以要等到同步任務和「任務隊列」現有的時間處理完纔會獲得執行。
複製代碼

僅用於我的整理,參考:post

promise、setTimeout、async的前後執行順序ui

淺析setTimeout與Promisespa

相關文章
相關標籤/搜索