先以一道面試題做引子:
寫出這段程序的輸出內容:
setTimeout(function(){ console.log(1); },0); new Promise(function(a,b){ console.log(2); for(var i=0;i<10;i++){ i==9&&a(); } console.log(3) }).then(function(){ console.log(4) }); console.log(5);
如果你看了這道題不知道怎么下手,或者發現結果和自己的答案大相徑庭,請繼續往下看
1. javascript事件循環
首先,你要知道javascript是單線程語言。js任務需要排隊順序執行,如果一個任務耗時過長,后邊一個任務也的等着,但是,假如我們需要瀏覽新聞,但新聞包含的超清圖片加載很慢,總不能網頁一直卡着直到圖片完全出來,所以將任務設計成了兩類:
同步任務
異步任務
當我們打開網站時,網頁的渲染過程就是一大堆同步任務,像頁面骨架和頁面元素的渲染,而加載圖片、音樂之類的任務就是異步任務,看一下下邊導圖:
如圖:
同步和異步任務分別進入不同的執行“場所”,同步進入主線程,異步進入Event Table並注冊函數。當指定的事情完成時,Event Table會將這個函數移入Event Queue。主線程內的任務執行完畢為空,回去了Event Queue讀取對應的函數,進入主線程。
上述過程會不斷重復,也就是常說的Event Loop(事件循環)。
但是,JS異步還有一個機制,就是遇到宏任務,先執行宏任務,將宏任務放入event queue,然后再執行微任務,將微任務放入eventqueue,但是,這兩個queue不是一個queue。當你往外拿的時候先從微任務里拿這個回調函數,然后再從宏任務的queue拿宏任務的回調函數,如下圖:
宏任務一般包括:整體代碼script,setTimeout,setInterval。
微任務:Promise,process.nextTick
參考文章: Javascript執行機制