經(jīng)典前端面試題:promise和setTimeout執(zhí)行順序是怎樣的?

要搞懂這個(gè)問(wèn)題,首先要了解事件循環(huán)(Event Loop)

JS運(yùn)行時(shí),對(duì)代碼執(zhí)行順序的一個(gè)算法(任務(wù)調(diào)度算法)

JS 分類:同步任務(wù)和異步任務(wù)
JS 的執(zhí)行機(jī)制:

  • 首先判斷JS代碼是同步還是異步,同步就進(jìn)入主線程,異步就進(jìn)入 event table
  • 異步任務(wù)在 event table 中注冊(cè)函數(shù),當(dāng)滿足觸發(fā)條件后,被推入event queue
  • 同步任務(wù)進(jìn)入主線程后一直執(zhí)行,直到主線程空閑時(shí),才回去 event queue 中查看是否有可執(zhí)行的異步任務(wù),如果有就推入主線程

event loop 里有維護(hù)兩個(gè)不同的異步任務(wù)隊(duì)列

  • macro Tasks(宏任務(wù)):script(整體代碼), setTimeout, setInterval, setImmediate, I/O, UI rendering
  • micro Tasks(微任務(wù)):process.nextTick, Promise(瀏覽器實(shí)現(xiàn)的原生Promise), Object.observe, MutationObserver, MessageChannel

每次執(zhí)行一段代碼(一個(gè)script標(biāo)簽)都是一個(gè) macroTask
執(zhí)行流程:

  • event loop 開始
  • 從macro Tasks 隊(duì)列抽取一個(gè)任務(wù),執(zhí)行
  • micro Tasks 清空隊(duì)列執(zhí)行,若有任務(wù)不可執(zhí)行,推入下一輪 micro Tasks
  • 結(jié)束 event loop

瀏覽器執(zhí)行代碼的過(guò)程如下整個(gè)流程


image

那么回到題目上去,就是

setTimeout(function(){
    console.log(1);    // 1-放入宏任務(wù)隊(duì)列,7-執(zhí)行下一輪事件循環(huán),宏任務(wù)輸出1
},0); 

new Promise(function(resolve) { 
    console.log(2);    // 2-同步輸出 2
    for(let i=0; i<10000 ; i++ ) { 
        i==9999 && resolve(); 
    } 
    console.log(3);    // 4-同步輸出 3
}).then(function(){ 
    console.log(4);    // 3-放入微任務(wù)隊(duì)列,6-回到微任務(wù)隊(duì)列,執(zhí)行剩余的微任務(wù),輸出4
}); 
console.log(5);    // 5-同步輸出 5

作者:FunnyZ


經(jīng)典前端面試題每日更新,歡迎參與討論,地址:https://github.com/daily-interview/fe-interview


更多angular1/2/4/5、ionic1/2/3、react、vue、微信小程序、nodejs等技術(shù)文章、視頻教程和開源項(xiàng)目,請(qǐng)關(guān)注微信公眾號(hào)——全棧弄潮兒。

image
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容