事情起因是这样的,我吹了个牛
然后小哥哥就真的给了我一个面试题!!!结果我发现自己不会!!!(╯ ̄Д ̄)╯╘═╛
不过现在会了,查漏补缺了。这篇文章主要涉及JavaScript的宏任务队列和微任务队列相关内容,后续有机会的话我可能整理一下JavaScript的异步?
首先来思考一下,这个代码输出什么。
const p = new Promise(function(resolve, reject) {
resolve();
setTimeout(() => {
console.log(1);
});
console.log(2);
}).then(res => {
console.log(3);
});
console.log(4);
答案是2 4 1 3
是不是很疑惑不知道为什么啊。JavaScript不是从上往下解析的吗,怎么这个顺序却这么混乱了。这就涉及到了异步问题。
异步执行顺序是怎么样的呢
js代码块解析的时候 同步的部分会顺序执行,异步的部分会存入MacroTask Queue(宏任务队列)和MicroTask Queue(微任务队列)。
MacroTask Queue(宏任务队列)主要包括:
setTimeout
,setInterval
,setImmediate
,requestAnimationFrame
,NodeJS中的I/O
,UI渲染
等。
MicroTask Queue(微任务队列)主要包括两类:
- 独立回调microTask:
Promise.then catch finally
,其成功/失败回调函数相互独立; - 复合回调microTask:
Object.observe
(已废弃),MutationObserver
和NodeJs中的 process.nextTick
,不同状态回调在同一函数体;
JS主线程不断的循环往复的从任务队列中读取任务,执行任务,这中运行机制称为事件循环(event loop)。
循环的过程如下:
- 执行同步代码直至执行完毕(解析执行到
</script>
标签); - 检查MicroTask队列
- 若有需处理的异步任务,依次执行所有已触发的异步任务直至执行完毕,然后检查MacroTask 队列
- 若没有需处理的异步任务中,则直接检查MacroTask 队列
- 检查MacroTask 队列
- 若有触发的异步任务,则取第一个加入MicroTask队列,对其进行处理,如此往复,依次执行下去直至所有任务执行结束。
看完上边这段。这个题就有解析了。
下图我已经标出来了。
- 同步代码
- promise创建就立即执行。
- 执行resolve()
- 遇到setTimeout,不执行,放入宏任务队列
- 遇到console.log(2),执行输出2
- .then 不执行,放入微任务队列
- 遇到console.log(4),输出4
- MicroTask队列:
- 有promise的.then,执行 console.log(3) 输出3
- MicroTask队列空,检查MacroTask 队列
- MacroTask队列:
- 有 setTimeout,将其放入MicroTask队列
- 检查 MicroTask队列
- MicroTask队列:
- 有 setTimeout,执行console.log(1),输出1
- MicroTask队列空,检查MacroTask 队列
- MacroTask队列:
- 队列空,结束事件循环
我好累啊