setTimeout与Promise的执行循序 | JavaScript MacroTask Queue(宏任务队列)和MicroTask Queue(微任务队列)

事情起因是这样的,我吹了个牛
在这里插入图片描述
然后小哥哥就真的给了我一个面试题!!!结果我发现自己不会!!!(╯ ̄Д ̄)╯╘═╛
不过现在会了,查漏补缺了。这篇文章主要涉及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(已废弃), MutationObserverNodeJs中的 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队列:
    • 队列空,结束事件循环

我好累啊

发布了131 篇原创文章 · 获赞 451 · 访问量 54万+

猜你喜欢

转载自blog.csdn.net/qq_36667170/article/details/105126891
今日推荐