宏任务和微任务和同步代码的执行的流程
执行栈在执行完同步任务后,查看执行栈是否为空,如果执行栈为空,就会去检查微任务(microTask)队列是否为空,如果为空的话,就执行Task(宏任务),否则就一次性执行完所有微任务。
每次单个宏任务执行完毕后,检查微任务(microTask)队列是否为空,如果不为空的话,会按照先入先出的规则全部执行完微任务(microTask)后,设置微任务(microTask)队列为null,然后再执行宏任务,如此循环。
总之,微任务的优先级要比宏任务的优先级高,同步代码会直接放到执行栈执行,优先级可以理解为最高。
宏任务:定时器的两个函数等等。
微任务:promise.then等等。
下面来看这个例子就很好理解了
setTimeout(()=>{
console.log("settimeout running")
new Promise(resolve=>{
console.log("settimeout promise running")
resolve()
})
.then(()=>{
console.log("settimeout promise then running")
})
},0)
new Promise((resolve)=>{
console.log("promise running")
resolve("promise then running")
})
.then((data)=>{
console.log(data)
setTimeout(()=>{
console.log("promise then settimeout running")
},0)
})
console.log("main running")
小伙伴们可能有点懵,这个执行顺序是什么呢?下面就给大家详细的分析。先来看结果
先说一点,定时器实际上有一个控制器,时间到了,就把定时器中的函数放到宏任务队列等待执行,我们这里统一设置0ms,所以就直接按放到宏任务队列来说了,但其实还是有控制器的这么一个过程。这个知道就好
首先从上到下,先将定时器中的部分放到宏任务队列排队等待,promise参数中函数的内容是同步代码,所以 1.输出promise running,同步代码执行后产生了一个异步任务(then中的代码),所以将这个异步任务放到微任务队列排队等待,接下来2.执行同步代码,输出 main running。到这里,最开始的两个同步任务已经执行完成,现在就剩微任务队列中的then,宏任务队列中的定时器。
我们说微任务的优先级是比宏任务高的,所以先执行then,3.输出 promise then running,输出之后这个微任务又产生了一个宏任务,将产生的宏任务放到宏任务队列。此时微任务队列为空了,执行宏任务队列,此时宏任务队列存在刚开始的定时器和刚刚微任务产生的定时器,4.输出 settimeout running,执行之后又产生一个同步代码,5.输出 settimeout promise running,之后又产生一个微任务then,将它放到微任务队列。
此时,微任务队列中存在任务,又转向执行该微任务,6.输出 settimeout promise then running,执行完之后,最后只剩下一个宏任务,7输出 promise then settimeout running。到这里是不是就理解了呢?是在没明白可以画两个队列和一个执行栈去模拟一下,就很容易理解喽!
再来一段代码,这里混合await
(async () => {
console.log(1);
setTimeout(() => {
console.log(2);
}, 0);
await new Promise((resolve, reject) => {
console.log(3);
// resolve()
}).then(() => {
console.log(4);
});
console.log(5);
})();
输出是132,这是因为这是立即执行函数,首先执行同步任务输出1,这个没有啥问题,下面产生一个宏任务放到后面,接下来注意await,它会等待promise的执行结果,只有当promise执行成功reject或者resolve并且回调函数都执行完成才会接着执行后续的代码,显然promise中没有resolve,所以then中的代码以及await之后的都不会执行了,接下来就是只有一个宏任务输出2 所以输出132
(async () => {
console.log(1);
setTimeout(() => {
console.log(2);
}, 0);
await new Promise((resolve, reject) => {
console.log(3);
resolve()
}).then(() => {
console.log(4);
});
console.log(5);
})();
这个就输出的是13452,这就是表示await会等待promise中的所有内容执行完成,包括回调函数全部执行完成之后才会执行后面的部分,其实也就是相当于加了await之后也成了同步代码。
如果明白了原理可以看下面博客的应用举例
宏任务微任务应用举例
最后推荐一个博主的视频,讲的很好
哔哩哔哩资源
文章是个人的理解,如有错误之处,还请大佬批评指正,也欢迎大家探讨交流。