MST

星途 面试题库

面试题:JavaScript事件循环中宏任务与微任务的执行顺序

请阐述JavaScript事件循环机制中宏任务队列和微任务队列的执行顺序,并举例说明不同任务类型(如setTimeout、Promise.then等)如何在这个机制下运行。
39.5万 热度难度
编程语言JavaScript

知识考点

AI 面试

面试题答案

一键面试

执行顺序

  1. 初始状态:JavaScript 引擎首次启动时,调用栈为空,微任务队列和宏任务队列初始也为空。
  2. 宏任务执行:引擎从宏任务队列中取出一个宏任务,放入调用栈执行。在执行过程中,可能会产生新的宏任务和微任务。
  3. 微任务执行:宏任务执行完毕后,引擎会检查微任务队列,将微任务队列中的所有任务依次取出放入调用栈执行,直到微任务队列为空。
  4. 循环:重复上述 2、3 步骤,不断从宏任务队列中取任务执行,执行完后处理微任务队列,形成事件循环。

示例说明

  1. setTimeout(宏任务)
console.log('script start');

setTimeout(() => {
    console.log('setTimeout');
}, 0);

console.log('script end');

在这段代码中,首先输出 script start,然后输出 script end。因为 setTimeout 是宏任务,会被放入宏任务队列,而当前代码属于主宏任务,主宏任务执行完毕后,才会从宏任务队列中取出 setTimeout 回调并执行,所以最后输出 setTimeout。 2. Promise.then(微任务)

console.log('script start');

Promise.resolve()
  .then(() => {
        console.log('Promise.then');
    });

console.log('script end');

这里先输出 script start,接着输出 script endPromise.resolve() 立即解决,其 .then 回调会被放入微任务队列。主宏任务执行完毕后,会处理微任务队列,所以最后输出 Promise.then。 3. 结合示例

console.log('script start');

setTimeout(() => {
    console.log('setTimeout1');

    Promise.resolve()
      .then(() => {
            console.log('Promise.then in setTimeout1');
        });
}, 0);

Promise.resolve()
  .then(() => {
        console.log('Promise.then1');
    });

setTimeout(() => {
    console.log('setTimeout2');
}, 0);

console.log('script end');

输出顺序为:script start -> script end -> Promise.then1 -> setTimeout1 -> Promise.then in setTimeout1 -> setTimeout2。主宏任务先执行,输出 script startscript end;然后处理微任务队列,输出 Promise.then1;接着从宏任务队列取出第一个 setTimeout 执行,输出 setTimeout1,在这个 setTimeout 执行过程中产生的微任务 Promise.then in setTimeout1 会在该宏任务执行完毕后加入微任务队列并执行;最后执行第二个 setTimeout,输出 setTimeout2