文章目录
简单总结一下在JS事件循环机制中微任务与宏任务。
宏任务:在调用栈中执行的代码(包括整体代码script, setTimeout, setInterval、 setlmmediate)
微任务:当前宏任务执行完毕,下个宏任务执行开始之前的任务称之为微任务(最常见的是promise.then, await)
接下来以一个实例详细分析微任务与宏任务的执行过程
首先看下面一段代码
<script>
async function async1() {
console.log('async1 start')
await async2()
console.log(666);
}
async function async2() {
setTimeout(() => {
console.log('setTimeout2')
}, 0)
}
console.log('script start')
setTimeout(() => {
console.log('setTimeout3')
}, 0);
async1()
new Promise(resolve => {
console.log('promise1')
resolve()
})
.then(() => {
console.log('promise2')
})
console.log('script end')
</script>
分析:
1.首先,完整的script代码为一个宏任务,宏任务从上往下执行,根据执行顺序,首先执行console.log(‘script start’)语句,此时打印出script start
2.接下来代码运行到定时器代码
setTimeout(() => {
console.log('setTimeout3')
}, 0);
由于定时器是一个宏任务,因此将该代码放入宏任务队列中,暂时不执行。
3.随后代码调用async1方法。如果async与await不是十分了解的话,可以将await的内容进行转换一下,具体转化如下所示。在执行过程中,首先执行console.log(‘async1 start’),因此async1 star被打印出来,接下来,执行定时器代码,由于又是一个定时器,因此将该也加入到宏任务队列中,执行完成后代码走到then方法处,由于promise.then是微任务,因此将console.log(666)放入微任务队列中。
//转换前
async function async1() {
console.log('async1 start')
await async2()
console.log(666);
}
async function async2() {
setTimeout(() => {
console.log('setTimeout2')
}, 0)
}
//转换后
async function async1() {
console.log('async1 start')
new Promise((resolve, reject) => {
setTimeout(() => {
console.log('setTimeout2')
}, 0)
resolve()
}).then(res => {
console.log(666);
})
}
//此时宏任务队列有两个任务,分别为:
setTimeout(() => {
console.log('setTimeout3')
}, 0);
setTimeout(() => {
console.log('setTimeout2')
}, 0)
//此时微任务队列有一个任务,为:
console.log(666);
//运行到此的输出内容为:
script start
async1 star
4.代码继续运行
new Promise(resolve => {
console.log('promise1')
resolve()
})
.then(() => {
console.log('promise2')
})
首先运行console.log(‘promise1’),输出promise1,随后将console.log(‘promise2’)添加到微任务队列。
//此时宏任务队列有两个任务,分别为:
setTimeout(() => {
console.log('setTimeout3')
}, 0);
setTimeout(() => {
console.log('setTimeout2')
}, 0)
//此时微任务队列有两个任务,为:
console.log(666);
console.log('promise2')
//运行到此的输出内容为:
script start
async1 star
promise1
5.代码继续运行
console.log('script end')
此时输出script end,到此为止,第一个完整的script代码宏任务执行完成,此时微任务队列有两个任务,宏任务队列有两个任务,此时已经输出的内容为
script start
async1 star
promise1
script end
6.由于存在微任务,因此先不执行宏任务队列,按照从上往下的顺序先执行微任务队列。
//微任务队列:
console.log(666);
console.log('promise2')
此时输出666 与 promise2
代码运行到此输出结果为
script start
async1 star
promise1
script end
666
promise2
7,微任务执行完成,接下来执行宏任务队列
setTimeout(() => {
console.log('setTimeout3')
}, 0);
setTimeout(() => {
console.log('setTimeout2')
}, 0)
第一个宏任务执行过程中没有产生微任务,因此输出完setTimeout3后,直接运行第二个宏任务,第二个宏任务输出setTimeout2。此时代码运行完毕。
最终输出结果为
script start
async1 star
promise1
script end
666
promise2
setTimeout3
setTimeout2
以上就是微任务与宏任务的运行过程,可以思考一下,如果是如下的代码,运行过程是怎样的呢?结果是什么?
<script>
async function async1() {
console.log('async1 start')
await async2()
console.log(666);
}
async function async2() {
setTimeout(() => {
console.log('setTimeout2')
}, 0)
}
console.log('script start')
setTimeout(() => {
console.log('setTimeout3')
}, 1000);
async1()
new Promise(resolve => {
console.log('promise1')
resolve()
})
.then(() => {
console.log('promise2')
})
console.log('script end')
</script>