持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第8天,点击查看活动详情
宏任务和微任务是面试题中会高频出现的考点,主要的形式是根据代码写出程序运行后的输出结果。
在此之前,需要先掌握什么是异步编程,以及宏任务和微任务的执行顺序。
预备知识
1.异步任务
分为宏任务和微任务,当一个宏任务执行完毕,会进入任务队列将里面的微任务全部执行完, 再进入下一个宏任务。
以下几种是在面试题中经常会遇到的几类任务:
-
宏任务(macrotask)
整体代码、setTimeOut、setInterval
-
微任务(microtask)
Promise.then、Promise.catch、Promise.finally(Promise中的代码段属于同步任务)
2.promise中的resolve()
- resolve()执行后,promise的状态会变为为fullfilled
- promise的状态为fullfilled后,promise.then()才会被执行:
- 如果没有执行resolve(),then里面的函数不会被推入微任务中
如下,这种属于立即执行的resolve(),它会在本轮事件循环完成前执行,并不会立即执行或者下一轮执行
Promise.resolve().then(function () {
console.log('1');
});
resolve里的参数就是传入then的数据
Promise.resolve('foo')
等价于:
new Promise(resolve => resolve('foo'))
例1
console.log('start')
setTimeout(function() {
console.log('A2')
}, 0)
Promise.resolve().then(function() {
console.log('A3')
})
new Promise(function(resolve, reject) {
console.log('A4')
setTimeout(function() {
console.log('A5')
resolve('A6')
}, 0)
}).then(res => {
console.log('A7')
setTimeout(function() {
console.log(res)
}, 0)
})
运行结果:
- start
- A4
- ------ (第一轮宏任务结束) ------- 微任务队列:无 ----- 宏任务队列:A2、A5 ------
- A2
- ------ (第二轮宏任务结束) ------- 微任务队列:A3 ----- 宏任务队列:A5 ------
- A3
- ------ (清空微任务队列结束) ------- 微任务队列:无 ----- 宏任务队列:A5 ------
- A5
- ------ (第三轮宏任务结束) ------- 微任务队列:A7 ----- 宏任务队列:res (即A6) ------
- A7
- ------ (清空微任务队列结束) ------- 微任务队列:无 ----- 宏任务队列:A6 ------
- A6
- ------ (第四轮宏任务结束) ------- 微任务队列:无 ----- 宏任务队列:无 ------
例2
const Fn = function() {
new Promise((resolve, reject) => {
const f1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('B1')
}, 0)
resolve('B2')
})
f1.then(res => {
console.log(res)
})
console.log('B3')
resolve('B4')
})
}
Fn.then(res => {
console.log('res')
})
console.log('End')
运行结果:
- B3
- End
- ------ (第一轮宏任务结束) ------- 微任务队列:无 ----- 宏任务队列:setTimeout('B1') ------
- ----- 执行resolve('B2') ,微任务队列:B2 -----
- B2
- ----- 执行resolve('B4') ,微任务队列:B4 -----
- B4
如果删掉resolve('B2'),运行结果为:
- B3
- End
- ----- 执行resolve('B4') ,微任务队列:B4 -----
- B4
- ----- 执行宏任务B1 -----
- B1