浏览器和 Node.js 中的事件循环有何区别?

2025-05-25

浏览器和 Node.js 中的事件循环有何区别?

每个 JS 开发者一定都听说过“事件循环”这个术语。JS 和 Node.js 都基于事件循环的原理,它们之间既有相似之处,也有不同之处。让我们简单讨论一下事件循环,并找出它们之间的区别。📖

浏览器中的事件循环

浏览器事件循环
让我们在这里简要介绍一下每个部分:

  1. ——它存储我们在函数中定义的所有对象引用和变量。

  2. 调用堆栈- 我们在代码中使用的所有函数都以后进先出 (LIFO) 的方式堆叠在这里,以便最后一个函数位于顶部,第一个函数位于底部。

  3. Web API - 这些 API 由浏览器提供,它通过 V8 引擎提供额外的功能。使用这些 API 的函数会被推送到此容器,Web API 响应完成后,会从此容器中弹出。

  4. 队列- 队列用于计算异步代码响应,以便它不会阻止引擎进一步执行。

    • 宏任务队列- 此队列执行异步函数,如 DOM 事件、Ajax 调用和 setTimeout,其优先级低于作业队列。
    • 微任务队列- 此队列执行使用承诺的异步函数,并且优先级高于消息队列。

事件循环检查调用栈,如果栈为空,则将队列中的函数推送到调用栈并运行。与消息队列中的函数相比,已存在的函数具有更高的优先级,将优先运行。

Node.js 中的事件循环

Node.js 事件循环

Node服务器由以下部分组成:

  1. 事件队列- 线程池执行完成后,会发出一个回调函数并将其发送到事件队列。当调用堆栈为空时,事件将进入事件队列,并将回调发送到调用堆栈。

  2. 线程池- 线程池由 4 个线程组成,用于委托那些对于事件循环来说过于繁重的操作。例如,I/O 操作、打开和关闭连接以及 setTimeouts 等。

  3. Node.js 中的事件循环分为不同的阶段,每个阶段都有一个 FIFO队列来执行回调。当事件循环进入某个阶段时,它会执行该阶段队列中的回调,直到队列耗尽且回调数量达到最大值,然后进入下一个阶段。

Node.js 事件循环阶段

事件循环是一个无限循环,它等待任务,执行它们,然后休眠直到收到更多任务。只有当堆栈为空时,事件循环才会从队列中执行任务。它首先处理最早的任务,并允许我们使用回调和 Promise。

两个事件循环之间有什么区别?

  1. 第一个区别是 Node 使用线程池来管理磁盘 I/O。它异步执行 I/O 和其他计时器 API。

  2. 浏览器没有setImmediate()函数。该函数会在 I/O 操作完成后执行,如果其中包含特定代码,则会优先执行。而setTimeout()回调函数则会在指定的最小阈值(以毫秒为单位)后执行。

  3. Node Js 事件循环有多个阶段,每个阶段处理特定类型的任务,而浏览器有微任务和宏任务队列,其中所有任务都按照放入队列的顺序进行处理。

  4. 在浏览器中,当你在标签页中打开一个页面时,你实际上创建了一个可以包含多个线程的进程,例如 JS 引擎、页面渲染、HTTP 请求线程等等。而在 Node.js 中,当你发起一个执行阻塞 I/O 操作的客户端请求时,事件循环会选择一个线程并将客户端请求分配给该线程,因为事件循环是单线程的。

这些是 Node.js 和浏览器事件循环之间的一些主要区别。如果我遗漏了什么,请告诉我 😅

学习愉快!👩🏻‍💻

文章来源:https://dev.to/jasmin/difference- Between-the-event-loop-in-browser-and-node-js-1113
PREV
如何将 HTML 网页转换为图像?
NEXT
Typescript - 超越基础