js的事件轮询机制

920 阅读2分钟

事件轮询机制

JavaScript 是一种单线程语言,这意味着它在同一时间只能执行一个任务。然而,JavaScript 通过事件轮询机制实现了高效的异步操作处理,使得它可以非阻塞地执行 I/O 操作和其他耗时任务。

事件轮询机制的核心组成部分包括:

  • 调用栈(Call Stack) :用于跟踪和管理函数的调用顺序。当函数被调用时,它会被添加到栈顶;当函数执行完毕后,从栈中移除。
  • 任务队列(Task Queue) :存放宏任务(Macrotask),如 setTimeoutsetInterval 和用户交互事件等。每个宏任务完成后,其回调函数将被加入此队列。
  • 微任务队列(Microtask Queue) :包含微任务(Microtask),例如 Promise 回调、process.nextTick(Node.js 环境)和 MutationObserver。这些任务会在当前宏任务结束后立即执行,但在下一轮宏任务开始之前。

事件轮询的工作流程如下:

  1. 执行同步代码,即调用栈中的所有任务。
  2. 调用栈清空后,引擎会检查并执行微任务队列中的所有任务,直到队列为空。
  3. 如果需要,浏览器可能会在此时进行页面渲染更新。
  4. 最后,从任务队列中取出下一个宏任务并重复上述过程。

宏任务与微任务的区别在于它们的执行时机:

  • 宏任务每次仅执行一个,并且在每次循环结束时触发。
  • 微任务则是在每次宏任务执行完后立即全部执行,确保在下一次宏任务前完成。

示例代码的执行顺序展示了这一点:

javascript
深色版本
console.log('Script start');

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

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

console.log('Script end');

这段代码会输出:

深色版本
Script start
Script end
Micro task
Macro task

这是因为所有的同步代码先被执行,接着是所有可用的微任务,最后才是宏任务的回调。


这种回答方式简洁明了,同时涵盖了关键概念和技术细节,适合作为面试中的专业回答。