面试题答案
一键面试-
执行顺序:
start
end
promise1
promise2
setTimeout2
promise3
setTimeout1
-
基于Event Loop、宏任务队列、微任务队列机制的解释:
- 初始执行:
- 代码开始执行,首先打印
start
。 - 遇到
Promise.resolve().then(() => {... })
,Promise.resolve()
返回一个已解决状态的Promise,其.then()
回调会被放入微任务队列。 - 遇到
setTimeout(() => {... }, 0)
,这是一个宏任务,会被放入宏任务队列。 - 打印
end
,主线程代码执行完毕。
- 代码开始执行,首先打印
- 第一轮Event Loop:
- 此时主线程空闲,Event Loop开始工作。
- 先检查微任务队列,发现有
Promise.resolve().then(() => {... })
的回调,执行该回调,打印promise1
。 - 在这个回调中又遇到
setTimeout(() => {... }, 0)
,这是一个新的宏任务,放入宏任务队列。 - 又遇到
Promise.resolve().then(() => {... })
,其回调放入微任务队列。 - 微任务队列执行完毕,开始检查宏任务队列。
- 第二轮Event Loop:
- 宏任务队列中有之前放入的
setTimeout(() => {... }, 0)
(即setTimeout2
相关的宏任务),执行该宏任务,打印setTimeout2
。 - 在这个宏任务中遇到
Promise.resolve().then(() => {... })
,其回调放入微任务队列。 - 宏任务执行完毕,再次检查微任务队列。
- 宏任务队列中有之前放入的
- 第三轮Event Loop:
- 微任务队列中有之前
promise1
回调中放入的Promise.resolve().then(() => {... })
(打印promise2
)和setTimeout2
宏任务中放入的Promise.resolve().then(() => {... })
(打印promise3
),按顺序执行,分别打印promise2
和promise3
。 - 微任务队列执行完毕,再次检查宏任务队列。
- 微任务队列中有之前
- 第四轮Event Loop:
- 宏任务队列中有
promise1
回调中放入的setTimeout(() => {... }, 0)
(即setTimeout1
相关的宏任务),执行该宏任务,打印setTimeout1
。 - 宏任务执行完毕,微任务队列为空,Event Loop结束。
- 宏任务队列中有
- 初始执行:
在JavaScript中,宏任务(如setTimeout
、setInterval
等)和微任务(如Promise.then
、MutationObserver
等)有不同的执行时机。Event Loop会在主线程空闲时,优先执行微任务队列中的任务,直到微任务队列清空,然后再从宏任务队列中取出一个任务执行,如此循环。