先看一到面試題
寫出console.log的輸出順序
console.log(100);
setTimeout(()=>{
console.log(200);
})
setTimeout(()=>{
console.log(201);
})
Promise.resolve().then(()=>{
console.log(300);
})
console.log(400);
// 100 400 300 200 201
// 為什么300比200先列印
為什么300比200先列印這里就引出了宏任務和微任務????
什么是宏任務和微任務

宏任務包括:setTimeout setInterval Ajax DOM事件
微任務:Promise async/await
微任務比宏任務的執行時間要早
同步異步問題
首先,你要知道javascript是單執行緒語言,js任務需要排隊順序執行,如果一個任務耗時過長,后邊一個任務也的等著,但是,假如我們需要瀏覽新聞,但新聞包含的超清圖片加載很慢,總不能網頁一直卡著直到圖片完全出來,所以將任務設計成了兩類:
同步任務
異步任務
當我們打開網站時,網頁的渲染程序就是一大堆同步任務,像頁面骨架和頁面元素的渲染,而加載圖片、音樂之類的任務就是異步任務,看一下下邊導圖:

同步和異步任務分別進入不同的執行“場所”,同步進入主執行緒,異步進入Event Table并注冊函式,當指定的事情完成時,Event Table會將這個函式移入Event Queue,主執行緒內的任務執行完畢為空,回去了Event Queue讀取對應的函式,進入主執行緒,
上述程序會不斷重復,也就是常說的Event Loop(事件回圈),
但是,JS異步還有一個機制,就是遇到宏任務,先執行宏任務,將宏任務放入event queue,然后再執行微任務,將微任務放入micro task queue,但是,這兩個queue不是一個queue,當你往外拿的時候先從微任務里拿這個回呼函式,然后再從宏任務的queue拿宏任務的回呼函式,如下圖:


所以最終的執行步驟為:
先是將所有同步代碼執行完畢后,call back(任務堆疊)清空
然后執行當前的微任務
然后執行當前的宏任務
再嘗試DOM的渲染
最后觸發Event Loop
三、執行順序
1.主執行緒上宏任務、微任務執行順序
console.log('---start---');//第一輪主執行緒
setTimeout(() => {
console.log('setTimeout'); // 將回呼代碼放入個宏任務佇列,第二輪宏任務執行
}, 0);
new Promise((resolve, reject) => {
console.log('---Promise第一輪微任務同步執行---');//第一輪微任務同步執行
resolve()
}).then(()=>{
console.log('Promise.then實體成功回呼執行'); // 將回呼代碼放入微任務佇列,第一輪宏任務執行完后立即執行
});
console.log('---end---');//第一輪主執行緒結束

執行順序:主執行緒 >> 主執行緒上創建的微任務 >> 主執行緒上創建的宏任務
2.宏任務中包含微任務
// 宏任務佇列 1
setTimeout(() => {
// 宏任務佇列 2.1
console.log('timer_1');
setTimeout(() => {
// 宏任務佇列 3
console.log('timer_3')
}, 0)
new Promise(resolve => {
resolve()
console.log('new promise')
}).then(() => {
// 微任務佇列 1
console.log('promise then')
})
}, 0)
setTimeout(() => {
// 宏任務佇列 2.2
console.log('timer_2')
}, 0)
console.log('========== Sync queue ==========')
執行順序:主執行緒 >> 主執行緒上的宏任務佇列1 >> 宏任務佇列1中創建的微任務
========== Sync queue ==========
1 timer_1
2 new promise
3 promise then
4 timer_2
5 timer_3
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/163073.html
標籤:其他
