EventLoop又叫事件循環,用來控制瀏覽器中事件的執行過程。javascript
以下圖所示,瀏覽器存在執行棧(單線程執行JS代碼)、任務隊列及一些WEB API。java
在瀏覽器中運行以下代碼:promise
console.log(1);
setTimeout(function(){
console.log(2);
}, 5000);
console.log(3);
// 輸出:
// 1
// 3
// 2
複製代碼
執行過程以下(演示地址):瀏覽器
console.log
,輸出1setTimeout
,啓動定時器console.log
,輸出3console.log
,輸出2理解了這個執行過程,就能明白爲何下面代碼(setTimeout時間設爲0)的輸出結果與上面相同:異步
console.log(1);
setTimeout(function(){
console.log(2);
}, 0);
console.log(3);
// 輸出:
// 1
// 3
// 2
複製代碼
執行過程:oop
console.log
,輸出1setTimeout
,啓動定時器console.log
,輸出3console.log
,輸出2並非全部異步任務的執行優先級都相同,微任務(microtask)比宏任務(macrotask)要優先執行。post
在瀏覽器環境中,常見的宏任務有setTimeout
、MessageChannel
、postMessage
、setImmediate
;常見的微任務有MutationObsever
和Promise.then
。ui
從下面這段代碼來看瀏覽器的執行過程:spa
setTimeout(() => {
console.log('timeout1');
Promise.resolve().then(() => {
console.log('promise1');
});
Promise.resolve().then(() => {
console.log('promise2');
});
}, 0);
setTimeout(() => {
console.log('timeout2');
Promise.resolve().then(() => {
console.log('promise3')
});
}, 0);
// 輸出:
// timeout1
// promise1
// promise2
// timeout2
// promise3
複製代碼
如下爲詳細執行過程:.net
setTimeout
,啓動定時器1
定時器1
時間到,將回調T1
放入宏任務隊列
setTimeout
,啓動定時器2
定時器2
時間到,將回調T2
放入宏任務隊列
回調T1
,放入執行棧
console.log
,輸出timeout1
Promise.then
,將回調P1
放入微任務隊列
Promise.then
,將回調P2
放入微任務隊列
回調P1
,放入執行棧
console.log
,輸出promise1
回調P2
,放入執行棧
console.log
,輸出promise2
回調T2
,放入執行棧
console.log
,輸出timeout2
Promise.then
,將回調P3
放入微任務隊列
回調P3
,放入執行棧
console.log
,輸出promise3
參考資料: