初探事件循環-Event Loop

  最近面試遇到這樣一道面試題:

console.log(1);
setTimeout(()=> {
    console.log(2);
},1000);
setTimeout(() => {
    console.log(3);
},0);
new Promise((resolve, reject) => {
    console.log(4);
    resolve();
}).then(() => {
    console.log(5);
}).then(() => {
    console.log(6)
})
console.log(7);
new Promise((resolve, reject) => {
    console.log(8);
    resolve();
}).then(() => {
    console.log(9);
}).then(() => {
    console.log(10)
})

問:上述代碼的輸出結果是啥?
答:1、4、7、8、5、9、6、10、3、2

  爲什麼輸出結果是上邊這樣的順序呢?promise的then回調函數會在setTimeout(function () {}, 0);之前輸出呢?我們可以先從事件循環說起:
  Javascript是單線程的,在執行時,會先執行同步代碼,遇到異步執行的代碼,會先將代碼放入到任務隊列中,主線程的代碼執行完畢,就會從任務隊列中取出任務執行。 按照當前描述,Javascript會先執行同步代碼,即console.log()函數和promise實例對象;然後,將其餘的異步函數加入到任務隊列中。
  接下來,promise的then回調和setTimeout函數,都是異步執行,那麼爲什麼promise的then回調會在setTimeout之前輸出呢?原因如下:
  在JavaScript中,任務隊列不止有一個,包含:MacroTask和MicroTask,在Javascript中可以包含多個MacroTask,但是隻能包含一個MicroTask,在代碼執行中,異步事件會根據自己的類型加入到不同的任務隊列中。
  Javascript開始執行事件時,會先清空函數調用棧,然後先執行MicroTask任務,再執行MacroTask;在執行這兩個任務隊列時,會先將MicroTask任務隊列清空,然後再去執行MacroTask隊列中的一個。然後循環執行…

MicroTask: Promise、Object.observe
MacroTask: setTimeout、setInterval、setImmediate、UI渲染

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