MST

星途 面试题库

面试题:JavaScript 中事件循环如何配合单线程模型处理异步任务

请详细阐述在 JavaScript 单线程模型下,事件循环是怎样工作来处理诸如 setTimeout、Promise 等异步任务的,举例说明执行顺序。
11.1万 热度难度
编程语言JavaScript

知识考点

AI 面试

面试题答案

一键面试

1. JavaScript 单线程模型

JavaScript 是单线程语言,意味着同一时间只能执行一个任务,它的执行环境只有一个调用栈(Call Stack)。这是为了避免 DOM 操作等冲突,如果是多线程同时操作 DOM,会引发不可预测的结果。

2. 异步任务处理机制 - 事件循环(Event Loop)

  • 任务队列(Task Queue):也叫宏任务队列(Macro Task Queue)。像 setTimeoutsetIntervalDOM 事件AJAX 请求 等产生的任务会被放入任务队列。
  • 微任务队列(Micro Task Queue)Promise.thenMutationObserver 等产生的任务会被放入微任务队列。微任务的优先级高于宏任务。
  • 事件循环流程
    • 首先,JavaScript 引擎会先执行调用栈中的同步任务。
    • 当调用栈为空时,引擎会检查微任务队列,如果微任务队列中有任务,就会依次执行微任务队列中的所有任务,直到微任务队列为空。
    • 然后,引擎会从宏任务队列中取出一个任务放入调用栈执行,执行完后再次检查微任务队列并执行其中所有任务,如此循环往复,这就是事件循环。

3. 举例说明执行顺序

console.log('script start');

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

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

console.log('script end');
  • 执行步骤
    • 首先,打印 script start,这是同步任务。
    • 遇到 setTimeout,它是宏任务,被放入宏任务队列。
    • 遇到 Promise.resolve()Promise.then 回调是微任务,被放入微任务队列。
    • 打印 script end,这是同步任务。
    • 此时调用栈为空,检查微任务队列,执行微任务。先打印 Promise1,然后 Promise2,直到微任务队列为空。
    • 再从宏任务队列中取出 setTimeout 任务放入调用栈执行,打印 setTimeout

最终输出顺序为:

script start
script end
Promise1
Promise2
setTimeout