宏任务与微任务相关知识点属于前端基础,掌握它对于项目优化和解决遇到的问题很有帮助,将我学习到的mark在此,以备忘了后查。
首先,先看一下下面这道题,列出输出的内容:
console.log(1);
setTimeout(() => console.log(2));
Promise.resolve().then(() => console.log(3));
Promise.resolve().then(() => setTimeout(() => console.log(4)));
Promise.resolve().then(() => console.log(5));
setTimeout(() => console.log(6));
console.log(7);
先公布答案,输出依次为:1,7,3,5,2,6,4。
要解释为什么,需要先解释清楚几个概念:
- 常规事件流:按顺序同步执行。
- 队列:像排队一样,先进先执行,后进后执行。
- 宏队列:例如script加载的内容、setTimeout、setInterval等。
- 微队列:promise的
.then
、.catch
、. finally
。
JavaScript是单线程。当遇到异步加载时候,存在两个队列:宏队列、微队列。他们各司其职,处理对应的任务。具体顺序是,先执行常规事件流,再执行微队列,最后执行宏队列,当循环完成后,js引擎休息等待下一次循环。
好了,概念说完了,是不是很简单。下面我们回到上面那道题。我们从上到下演示一下各队列的现状。
console.log(1); //常规事件流
// 此时,宏队列:空; 微队列:空
setTimeout(() => console.log(2)); //加入宏队列
// 此时,宏队列:[console.log(2)]; 微队列:空
Promise.resolve().then(() => console.log(3)); //加入微队列
// 此时,宏队列:[console.log(2)]; 微队列:[console.log(3)]
Promise.resolve().then(() => setTimeout(() => console.log(4))); //加入微队列
// 此时,宏队列:[console.log(2)]; 微队列:[console.log(3),setTimeout(() => console.log(4))]
Promise.resolve().then(() => console.log(5));//加入微队列
// 此时,宏队列:[console.log(2)]; 微队列:[console.log(3),setTimeout(() => console.log(4)),console.log(5)]
setTimeout(() => console.log(6));//加入宏队列
// 此时,宏队列:[console.log(2),console.log(6)]; 微队列:[console.log(3),setTimeout(() => console.log(4)),console.log(5)]
console.log(7); //常规事件流
- 1,7是常规事件流,直接输出。
- 接下来开始执行微队列。因为setTimeout是宏任务,继续添加到宏队列中,此时,
宏队列:[console.log(2),console.log(6),console.log(4)]; 微队列:[console.log(3),console.log(5)]
,则微任务队列中依次输出3,5。 - 宏队列依次输出2,6,4。
吐槽一句:本来很简单的道理,很简单就能解释清楚的问题,有些网友的解释真的是极度的复杂啊,害得我浪费了好多脑细胞。。。还有些抄来抄去的结论根本不对,误导啊。。。
THE END