动态

详情 返回 返回

【前端面試】V8事件輪詢 - 动态 详情

在前端面試中,面試官可能會問你V8的引擎機制,給你這樣的一道題目如下:

console.log(1);

setTimeout(() => {
 console.log(2);
});

new Promise(reslove => {
  console.log(3);
  reslove();
}).then(() => {
  console.log(4);
});

console.log(5);

面試官會讓你給出題目中輸出的順序以及執行原理

直接在瀏覽器運行我們可以知道輸出的順序是1、3、5、4、2,那這過程中到底為什麼會這樣輸出呢?要了解這個打印順序的原理,我們必須弄清楚V8的事件輪詢機制。下面是一張原理圖:

圖片

裏面涉及到兩個概念,一個是宏任務MacroTask,一個是微任務MicroTask。其中MacroTask所存放的任務隊列有setTimeout,setinterval。MicroTask裏面所存放的隊列有Promise,.then,還有process,.nextTick等等。

它輪詢具體的方式是,我們這裏假定一個流程,如下圖:

圖片

從開始執行,代碼優先執行同步的script片段,然後我們就一直把同步的執行完。執行完同步之後的我們一旦遇到有異步的代碼,我們就開始進入任務類型的判斷,如果判斷應該存放於MacroTask的,我們就放到宏任務隊列裏,如果需要放到MicroTask,我們就存放到微任務隊列裏。

等到所有的同步代碼執行完畢之後,我們優先從微任務裏面去把任務拉取出來執行,其次才是從宏任務隊列裏面拉任務出來執行,然後如此遞歸循環,直到把所有代碼片段執行完畢。

分析:

我們再來回顧看一下上面題目裏面的代碼:

圖片

1.我們首先第一段console.log(1),那我們直接打印1。

2.然後再到setTimeout裏面有一個console.log(2),那我們就把這個console.log(2)放到MacroTask隊列。

3.然後進而我們看到new Promise,它是構造函數,那直接打印3,再到.then裏面console.log(4),我們就放到MicroTask隊列裏面,也是微任務隊列。

4.最後就是console.log(5),直接打印5。

總結:

所以經歷過第一遍分析之後,我們打印了1、3、5,等所有代碼執行完畢之後,我們優先從微任務裏面把代碼片段抽取出來,那就從console.log(4)提取出來並執行,那就打印4,最後從宏任務隊列裏面拿出console.log(2)出來執行,所以打印2。這樣下來整體的順序就會打印成1、3、5、4、2

user avatar guochenglong 头像 segmentfault 头像 freeman_tian 头像 jingdongkeji 头像 joe235 头像 abc-x 头像 geeklab 头像 haixiudezhusun 头像 zhaodawan 头像 beckyyyy 头像 taotao123 头像 hightopo 头像
点赞 48 用户, 点赞了这篇动态!
点赞

Add a new 评论

Some HTML is okay.