关于JS中微任务与宏任务这件事

文章目录


简单总结一下在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>

版权声明:本文为qq_45847016原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。