一、原理圖
二杯聚、定義說明
JS 中用來存儲待執(zhí)行回調(diào)函數(shù)的隊(duì)列包含 2 個(gè)不同特定的列隊(duì)
宏列隊(duì):用來保存待執(zhí)行的宏任務(wù)(回調(diào))臼婆,比如:定時(shí)器回調(diào)、DOM 事件回調(diào)械媒、ajax 回調(diào)
微列隊(duì):用來保存待執(zhí)行的微任務(wù)(回調(diào))目锭,比如:promise的回調(diào)、MutationObserver 的回調(diào)
JS 引擎首先必須先執(zhí)行所有的初始化同步任務(wù)代碼
每次準(zhǔn)備取出第一個(gè)宏任務(wù)執(zhí)行前, 都要將所有的微任務(wù)一個(gè)一個(gè)取出來執(zhí)行纷捞,也就是優(yōu)先級比宏任務(wù)高,且與微任務(wù)所處的代碼位置無關(guān)
下面這個(gè)例子可以看出 Promise 要先于 setTimeout 執(zhí)行:
setTimeout(() => { //立即放入宏隊(duì)列
console.log('timeout callback1()')
Promise.resolve(3).then(
value => { //立即放入微隊(duì)列
console.log('Promise onResolved3()', value)
}
)
}, 0)
setTimeout(() => { //立即放入宏隊(duì)列
console.log('timeout callback2()')
}, 0)
Promise.resolve(1).then(
value => { //立即放入微隊(duì)列
console.log('Promise onResolved1()', value)
setTimeout(() => {
console.log('timeout callback3()', value)
}, 0)
}
)
Promise.resolve(2).then(
value => { //立即放入微隊(duì)列
console.log('Promise onResolved2()', value)
}
)
// Promise onResolved1() 1
// Promise onResolved2() 2
// timeout callback1()
// Promise onResolved3() 3
// timeout callback2()
// timeout callback3() 1
三被去、面試題
1. 題目一
// 3 7 4 1 2 5
/*
宏: []
微: []
*/
const first = () => (new Promise((resolve, reject) => {
console.log(3)
let p = new Promise((resolve, reject) => {
console.log(7)
setTimeout(() => {
console.log(5)
resolve(6) //會被忽略主儡,因?yàn)闀葓?zhí)行微隊(duì)列里的resolve(1),此時(shí)狀態(tài)已經(jīng)改變過了惨缆,且狀態(tài)只能改變一次
}, 0)
resolve(1)
})
resolve(2)
p.then((arg) => {
console.log(arg)
})
}))
first().then((arg) => {
console.log(arg)
})
console.log(4)
2. 題目二
// 1 7 2 3 8 4 6 5 0
setTimeout(() => {
console.log("0")
}, 0)
new Promise((resolve, reject) => {
console.log("1")
resolve()
}).then(() => {
console.log("2")
new Promise((resolve, reject) => {
console.log("3")
resolve()
}).then(() => {
console.log("4")
}).then(() => {
console.log("5")
})
}).then(() => {
console.log("6")
})
new Promise((resolve, reject) => {
console.log("7")
resolve()
}).then(() => {
console.log("8")
})