案例一:
求下面代码的运行输出结果
new Promise((res) => {
setTimeout(() => {
console.log(1);
res()
}, 0);
console.log(2);
}).then(() => {
console.log(3);
})
console.log(4);
第一步,先将代码全部注释:
// new Promise((res) => {
// setTimeout(() => {
// console.log(1);
// res()
// }, 0);
// console.log(2);
// }).then(() => {
// console.log(3);
// })
// console.log(4);
从上到下,依次执行代码。
new Promise是同步任务,立即执行:
new Promise((res) => {
// setTimeout(() => {
// console.log(1);
// res()
// }, 0);
// console.log(2);
})
// .then(() => {
// console.log(3);
// })
// console.log(4);
setTimeout是宏任务,放入宏任务队列
new Promise((res) => {
// setTimeout(() => { //宏任务1
// console.log(1);
// res()
// }, 0);
// console.log(2);
})
// .then(() => {
// console.log(3);
// })
// console.log(4);
//宏:1
console.log(2)是同步任务,立即执行
new Promise((res) => {
// setTimeout(() => { //宏任务1
// console.log(1);
// res()
// }, 0);
console.log(2); //执行,输出2
})
// .then(() => {
// console.log(3);
// })
// console.log(4);
//宏:1
//输出:2
console.log(4)是同步任务,执行
new Promise((res) => {
// setTimeout(() => { //宏任务1
// console.log(1);
// res()
// }, 0);
console.log(2); //执行,输出2
})
// .then(() => {
// console.log(3);
// })
console.log(4);
//宏:1
//输出:2 4
扫描完毕,所有同步任务都执行完成,现在先查看微任务队列是否有任务。此时没有,则看宏任务队列是否有任务,有一个“1”,执行宏任务1。
new Promise((res) => {
setTimeout(() => { //宏任务1
// console.log(1);
// res()
}, 0);
console.log(2); //执行,输出2
})
// .then(() => {
// console.log(3);
// })
console.log(4);
//宏:
//输出:2 4
console.log(1) 是同步任务,执行
new Promise((res) => {
setTimeout(() => { //宏任务1
console.log(1); //执行,输出1
// res()
}, 0);
console.log(2); //执行,输出2
})
// .then(() => {
// console.log(3);
// })
console.log(4);
//宏:
//输出:2 4 1
res()是同步任务,执行。此函数执行后,promise的then钩子函数被激活,但是它是个微任务。
new Promise((res) => {
setTimeout(() => { //宏任务1
console.log(1); //执行,输出1
res() //执行,释放微任务1
}, 0);
console.log(2); //执行,输出2
})
// .then(() => { //微任务1
// console.log(3);
// })
console.log(4);
//宏:
//微:1
//输出:2 4 1
同步任务执行完毕,执行微任务1
new Promise((res) => {
setTimeout(() => { //宏任务1
console.log(1); //执行,输出1
res() //执行,释放微任务1
}, 0);
console.log(2); //执行,输出2
})
.then(() => { //微任务1
// console.log(3);
})
console.log(4);
//宏:
//微:
//输出:2 4 1
console.log(3)是同步任务,执行
new Promise((res) => {
setTimeout(() => { //宏任务1
console.log(1); //执行,输出1
res() //执行,释放微任务1
}, 0);
console.log(2); //执行,输出2
})
.then(() => { //微任务1
console.log(3); //执行,输出3
})
console.log(4);
//宏:
//微:
//输出:2 4 1 3
输出结果:2 4 13
案例二:
下面是一个比较复杂的案例,求出代码运行的输出结果:
setTimeout(() => {
console.log(1)
setTimeout(() => {
console.log(2)
}, 0)
}, 0)
new Promise((res) => {
new Promise((res) => {
setTimeout(() => {
console.log(3);
})
console.log(4);
res()
}).then(() => {
console.log(5);
})
console.log(6)
setTimeout(() => {
console.log(7)
setTimeout(() => {
console.log(8)
res()
}, 0)
}, 0)
}).then(() => {
console.log(9)
setTimeout(() => {
console.log(10)
}, 0)
new Promise((res) => {
console.log(11)
res()
}).then(() => {
console.log(12)
})
})
console.log(13)
首先:注释所有代码
// setTimeout(() => {
// console.log(1)
// setTimeout(() => {
// console.log(2)
// }, 0)
// }, 0)
// new Promise((res) => {
// new Promise((res) => {
// setTimeout(() => {
// console.log(3);
// })
// console.log(4);
// res()
// }).then(() => {
// console.log(5);
// })
// console.log(6)
// setTimeout(() => {
// console.log(7)
// setTimeout(() => {
// console.log(8)
// res()
// }, 0)
// }, 0)
// }).then(() => {
// console.log(9)
// setTimeout(() => {
// console.log(10)
// }, 0)
// new Promise((res) => {
// console.log(11)
// res()
// }).then(() => {
// console.log(12)
// })
// })
// console.log(13)
从现在开始,假设我们是JS引擎,开始解析代码。
从上往下扫描代码,按不同任务进行不同处理:
// setTimeout(() => { //宏任务1,放入宏任务队列
// console.log(1)
// setTimeout(() => {
// console.log(2)
// }, 0)
// }, 0)
new Promise((res) => { //同步任务,执行
new Promise((res) => { //同步任务,执行
// setTimeout(() => { //宏任务2,放入宏任务队列
// console.log(3);
// })
console.log(4); //同步任务,执行,输出4
res() //同步任务,执行,此语句释放出微任务1
})
// .then(() => { //微任务1,放入微任务队列
// console.log(5);
// })
console.log(6) //同步任务,执行,输出6
// setTimeout(() => { //宏任务3,放入宏任务队列
// console.log(7)
// setTimeout(() => {
// console.log(8)
// res()
// }, 0)
// }, 0)
})
// .then(() => {
// console.log(9)
// setTimeout(() => {
// console.log(10)
// }, 0)
// new Promise((res) => {
// console.log(11)
// res()
// }).then(() => {
// console.log(12)
// })
// })
console.log(13) //同步任务,执行,输出13
//宏任务队列: 1 2 3
//微任务队列: 1
//这一轮输出: 4 6 13
同步任务执行完成,发现微任务队列有任务,执行微任务1
// setTimeout(() => { //宏任务1,放入宏任务队列
// console.log(1)
// setTimeout(() => {
// console.log(2)
// }, 0)
// }, 0)
new Promise((res) => { //同步任务,执行
new Promise((res) => { //同步任务,执行
// setTimeout(() => { //宏任务2,放入宏任务队列
// console.log(3);
// })
console.log(4); //同步任务,执行,输出4
res() //同步任务,执行,此语句释放出微任务1
})
.then(() => { //微任务1,放入微任务队列->执行
console.log(5); //-----同步任务,执行,输出5
})
console.log(6) //同步任务,执行,输出6
// setTimeout(() => { //宏任务3,放入宏任务队列
// console.log(7)
// setTimeout(() => {
// console.log(8)
// res()
// }, 0)
// }, 0)
})
// .then(() => {
// console.log(9)
// setTimeout(() => {
// console.log(10)
// }, 0)
// new Promise((res) => {
// console.log(11)
// res()
// }).then(() => {
// console.log(12)
// })
// })
console.log(13) //同步任务,执行,输出13
//宏任务队列: 1 2 3
//微任务队列:
//这一轮输出: 4 6 13 5
微任务队列为空,宏任务队列有任务在排队,依次执行宏任务1、2、3
setTimeout(() => { //宏任务1,放入宏任务队列 --> 执行
console.log(1) //-----同步任务,输出1
// setTimeout(() => { //-----宏任务4,放入宏任务队列
// console.log(2)
// }, 0)
}, 0)
new Promise((res) => { //同步任务,执行
new Promise((res) => { //同步任务,执行
setTimeout(() => { //宏任务2,放入宏任务队列 --> 执行
console.log(3); //-----同步任务,执行,输出3
})
console.log(4); //同步任务,执行,输出4
res() //同步任务,执行,此语句释放出微任务1
})
.then(() => { //微任务1,放入微任务队列->执行
console.log(5); //-----同步任务,执行,输出5
})
console.log(6) //同步任务,执行,输出6
setTimeout(() => { //宏任务3,放入宏任务队列
console.log(7) //-----同步任务,执行,输出7
// setTimeout(() => { //-----宏任务5,放入宏任务队列
// console.log(8)
// res()
// }, 0)
}, 0)
})
// .then(() => {
// console.log(9)
// setTimeout(() => {
// console.log(10)
// }, 0)
// new Promise((res) => {
// console.log(11)
// res()
// }).then(() => {
// console.log(12)
// })
// })
console.log(13) //同步任务,执行,输出13
//宏任务队列: 4 5
//微任务队列:
//这一轮输出: 4 6 13 5 1 3 7
宏任务队列有任务在排队,依次执行宏任务4、5
setTimeout(() => { //宏任务1,放入宏任务队列 --> 执行
console.log(1) //-----同步任务,输出1
setTimeout(() => { //-----宏任务4,放入宏任务队列 --> 执行
console.log(2) //----------同步任务,执行,输出2
}, 0)
}, 0)
new Promise((res) => { //同步任务,执行
new Promise((res) => { //同步任务,执行
setTimeout(() => { //宏任务2,放入宏任务队列 --> 执行
console.log(3); //-----同步任务,执行,输出3
})
console.log(4); //同步任务,执行,输出4
res() //同步任务,执行,此语句释放出微任务1
})
.then(() => { //微任务1,放入微任务队列->执行
console.log(5); //-----同步任务,执行,输出5
})
console.log(6) //同步任务,执行,输出6
setTimeout(() => { //宏任务3,放入宏任务队列
console.log(7) //-----同步任务,执行,输出7
setTimeout(() => { //-----宏任务5,放入宏任务队列 --> 执行
console.log(8) //----------同步任务,执行,输出8
res() //----------同步任务,执行,此语句释放出微任务2
}, 0)
}, 0)
})
// .then(() => { //微任务2,放入微任务队列
// console.log(9)
// setTimeout(() => {
// console.log(10)
// }, 0)
// new Promise((res) => {
// console.log(11)
// res()
// }).then(() => {
// console.log(12)
// })
// })
console.log(13) //同步任务,执行,输出13
//宏任务队列:
//微任务队列: 2
//这一轮输出: 4 6 13 5 1 3 7 2 8
执行微任务2
setTimeout(() => { //宏任务1,放入宏任务队列 --> 执行
console.log(1) //-----同步任务,输出1
setTimeout(() => { //-----宏任务4,放入宏任务队列 --> 执行
console.log(2) //----------同步任务,执行,输出2
}, 0)
}, 0)
new Promise((res) => { //同步任务,执行
new Promise((res) => { //同步任务,执行
setTimeout(() => { //宏任务2,放入宏任务队列 --> 执行
console.log(3); //-----同步任务,执行,输出3
})
console.log(4); //同步任务,执行,输出4
res() //同步任务,执行,此语句释放出微任务1
})
.then(() => { //微任务1,放入微任务队列->执行
console.log(5); //-----同步任务,执行,输出5
})
console.log(6) //同步任务,执行,输出6
setTimeout(() => { //宏任务3,放入宏任务队列
console.log(7) //-----同步任务,执行,输出7
setTimeout(() => { //-----宏任务5,放入宏任务队列 --> 执行
console.log(8) //----------同步任务,执行,输出8
res() //----------同步任务,执行,此语句释放出微任务2
}, 0)
}, 0)
})
.then(() => { //微任务2,放入微任务队列 --> 执行
console.log(9) //---------------同步任务,执行,输出9
// setTimeout(() => { //---------------宏任务6,放入宏任务队列
// console.log(10)
// }, 0)
new Promise((res) => { //---------------同步任务,执行
console.log(11) //---------------同步任务,执行
res() //---------------同步任务,执行,此语句释放出微任务3
})
// .then(() => { //微任务3,放入微任务队列
// console.log(12)
// })
})
console.log(13) //同步任务,执行,输出13
//宏任务队列: 6
//微任务队列: 3
//这一轮输出: 4 6 13 5 1 3 7 2 8 9
执行微任务3:
setTimeout(() => { //宏任务1,放入宏任务队列 --> 执行
console.log(1) //-----同步任务,输出1
setTimeout(() => { //-----宏任务4,放入宏任务队列 --> 执行
console.log(2) //----------同步任务,执行,输出2
}, 0)
}, 0)
new Promise((res) => { //同步任务,执行
new Promise((res) => { //同步任务,执行
setTimeout(() => { //宏任务2,放入宏任务队列 --> 执行
console.log(3); //-----同步任务,执行,输出3
})
console.log(4); //同步任务,执行,输出4
res() //同步任务,执行,此语句释放出微任务1
})
.then(() => { //微任务1,放入微任务队列->执行
console.log(5); //-----同步任务,执行,输出5
})
console.log(6) //同步任务,执行,输出6
setTimeout(() => { //宏任务3,放入宏任务队列
console.log(7) //-----同步任务,执行,输出7
setTimeout(() => { //-----宏任务5,放入宏任务队列 --> 执行
console.log(8) //----------同步任务,执行,输出8
res() //----------同步任务,执行,此语句释放出微任务2
}, 0)
}, 0)
})
.then(() => { //微任务2,放入微任务队列 --> 执行
console.log(9) //---------------同步任务,执行,输出9
// setTimeout(() => { //---------------宏任务6,放入宏任务队列
// console.log(10)
// }, 0)
new Promise((res) => { //---------------同步任务,执行
console.log(11) //---------------同步任务,执行,输出11
res() //---------------同步任务,执行,此语句释放出微任务3
})
.then(() => { //微任务3,放入微任务队列 --> 执行
console.log(12) //--------------------同步任务,执行,输出12
})
})
console.log(13) //同步任务,执行,输出13
//宏任务队列: 6
//微任务队列:
//这一轮输出: 4 6 13 5 1 3 7 2 8 9 11 12
执行宏任务6
setTimeout(() => { //宏任务1,放入宏任务队列 --> 执行
console.log(1) //-----同步任务,输出1
setTimeout(() => { //-----宏任务4,放入宏任务队列 --> 执行
console.log(2) //----------同步任务,执行,输出2
}, 0)
}, 0)
new Promise((res) => { //同步任务,执行
new Promise((res) => { //同步任务,执行
setTimeout(() => { //宏任务2,放入宏任务队列 --> 执行
console.log(3); //-----同步任务,执行,输出3
})
console.log(4); //同步任务,执行,输出4
res() //同步任务,执行,此语句释放出微任务1
})
.then(() => { //微任务1,放入微任务队列->执行
console.log(5); //-----同步任务,执行,输出5
})
console.log(6) //同步任务,执行,输出6
setTimeout(() => { //宏任务3,放入宏任务队列
console.log(7) //-----同步任务,执行,输出7
setTimeout(() => { //-----宏任务5,放入宏任务队列 --> 执行
console.log(8) //----------同步任务,执行,输出8
res() //----------同步任务,执行,此语句释放出微任务2
}, 0)
}, 0)
})
.then(() => { //微任务2,放入微任务队列 --> 执行
console.log(9) //---------------同步任务,执行,输出9
setTimeout(() => { //---------------宏任务6,放入宏任务队列 --> 执行
console.log(10) //--------------------同步任务,执行,输出10
}, 0)
new Promise((res) => { //---------------同步任务,执行
console.log(11) //---------------同步任务,执行,输出11
res() //---------------同步任务,执行,此语句释放出微任务3
})
.then(() => { //微任务3,放入微任务队列 --> 执行
console.log(12) //--------------------同步任务,执行,输出12
})
})
console.log(13) //同步任务,执行,输出13
//宏任务队列:
//微任务队列:
//这一轮输出: 4 6 13 5 1 3 7 2 8 9 11 12 10
最终输出:4 6 13 5 1 3 7 2 8 9 11 12 10