MST

星途 面试题库

面试题:JavaScript 异步编程中 Event Loop 与微任务队列的复杂应用

在以下代码片段中:```javascript console.log('start'); Promise.resolve().then(() => { console.log('promise1'); setTimeout(() => { console.log('setTimeout1'); }, 0); Promise.resolve().then(() => { console.log('promise2'); }); }); setTimeout(() => { console.log('setTimeout2'); Promise.resolve().then(() => { console.log('promise3'); }); }, 0); console.log('end'); ```请详细分析这段代码的执行顺序,并结合 JavaScript 的 Event Loop、宏任务队列、微任务队列机制解释为什么会这样执行。
33.6万 热度难度
编程语言JavaScript

知识考点

AI 面试

面试题答案

一键面试
  1. 执行顺序

    • start
    • end
    • promise1
    • promise2
    • setTimeout2
    • promise3
    • setTimeout1
  2. 基于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),按顺序执行,分别打印promise2promise3
      • 微任务队列执行完毕,再次检查宏任务队列。
    • 第四轮Event Loop
      • 宏任务队列中有promise1回调中放入的setTimeout(() => {... }, 0)(即setTimeout1相关的宏任务),执行该宏任务,打印setTimeout1
      • 宏任务执行完毕,微任务队列为空,Event Loop结束。

在JavaScript中,宏任务(如setTimeoutsetInterval等)和微任务(如Promise.thenMutationObserver等)有不同的执行时机。Event Loop会在主线程空闲时,优先执行微任务队列中的任务,直到微任务队列清空,然后再从宏任务队列中取出一个任务执行,如此循环。