发布于 2026-01-05 18 阅读
0

使用 React.js 和 Node.js 的服务器发送事件 (SSE) 实现实时数据流传输

使用 React.js 和 Node.js 的服务器发送事件 (SSE) 实现实时数据流传输

我们生活在一个实时数据流至关重要的世界。实时数据流已成为现代应用程序的必需品,因为它能让用户在事件发生时立即收到通知。但我们在互联网上看到的绝大多数通信都涉及客户端应用程序向服务器发出请求,服务器处理请求并将响应发送回客户端。这需要时间处理,而且在某些情况下,服务器需要在客户端未主动发起请求的情况下向客户端发送数据。

这可以通过长轮询、WebSocket、Webhook 或服务器发送事件来实现。实时应用示例包括:即时通讯、通知系统、在线游戏、聊天应用、视频会议、数据流、体育赛事更新、股票价格等等。但本文主要关注服务器发送事件。

您还可以阅读

流处理范式:实现连续数据分析和转换

视频教程

如果您更喜欢观看和学习如何使用 React js 和 Node js 实现服务器发送事件 (SSE) 的深入教程,这里有一个完整的视频供您观看。

请不要忘记点赞、评论、订阅我的YouTube频道,并将视频分享给你的朋友们。

客户端-服务器通信的不同技术

以下是一些用于客户端-服务器通信的技术

轮询是一种应用程序反复从服务器获取数据的技术。如果您熟悉 HTTP 协议,它采用请求/响应模式。这是绝大多数 AJAX 应用程序使用的传统技术。轮询的缺点是会增加 HTTP 开销。

长轮询是一种技术,当客户端发出请求时,如果服务器没有可用的数据,服务器会保持请求连接打开,直到数据可用。当数据可用时,服务器会响应并关闭连接;客户端收到新数据后,会再次向服务器发送请求。这个循环会无限重复,直到任何一方关闭连接为止。这种机制的主要缺点是,一旦服务器发送了数据,就必须等到新的轮询请求到达才能发送后续数据。

WebSocket是一种通信协议,它通过单个 TCP 连接提供全双工双向通信通道。这种机制在服务器和客户端之间建立双向连接,即服务器可以向客户端发送数据,客户端也可以向服务器发送数据。这对于聊天应用、即时通讯等场景非常有用。
然而,有时我们需要从服务器获取一些更新,而无需等待客户端反复发起请求。例如,好友的在线状态更新、新闻推送等。

服务器发送事件 (Server-Sent Events,SSE)是一种 HTTP 标准,它允许客户端应用程序在建立初始连接后自动接收来自服务器的更新或事件流。它是一种服务器推送技术,允许客户端应用程序通过 HTTP 连接接收来自服务器的数据传输,并描述了服务器如何在建立初始连接后将数据流式传输到客户端。服务器发送事件 (SSE) 本质上是单向的,也就是说,只有服务器才能向客户端推送更新。SSE 通常用于向浏览器客户端发送自动更新或连续数据流。

服务器发送事件 (SSE) 与长轮询的主要区别在于,SSE 由浏览器直接处理,客户端应用程序只需监听消息即可。

JavaScript EventSource API 中包含的 SSE 用于打开与服务器的连接,以便持续接收事件流。在服务器发送的事件中,自动更新会直接发送给客户端,而不是从客户端拉取。

您还可以阅读

流处理范式:实现连续数据分析和转换

服务器发送事件与 WebSocket 的比较

WebSocket提供双向全双工通信。它创建了一个双向通道,客户端可以向服务器发送数据,服务器也可以向客户端发送数据。这使得双向实时通信成为可能。因此,它非常适用于实时聊天应用、游戏等场景。

然而,在某些情况下,客户端应用程序不需要向服务器发送数据,而只需要从服务器消费数据,这时服务器发送事件(SSE)就派上了用场。

在同步事件流(SSE)中,通信是单向的,也就是说,一旦建立初始连接,服务器就会持续地向客户端推送事件流。例如:实时通知系统、体育赛事更新、股票价格、状态更新、新闻推送、加密货币更新等。

服务器发送事件实现

服务器发送服务器既可以在服务器端实现,也可以在客户端实现。

客户端 API

SSE客户端API包含在EventSource对象中。
使用SSE时,浏览器会首先生成一个EventSource实例来建立与服务器的连接。

要检测浏览器是否支持 SSE,请使用以下代码片段;

const url = "http://localhost:5000/stream"
//url can be your server url

if ('EventSource' in window) {
  let source = new EventSource(url)
}

Enter fullscreen mode Exit fullscreen mode

注意:上述URL可以与应用程序的当前URL位于同一域,也可以跨域。当传递给EventSource构造函数的 URL 为绝对 URL 时,其源(协议、域名、端口)必须服务器的源匹配。

当跨域 URL 被传递时,您可以指定第二个 _options_ 参数,并使用withCredentials属性来指示是否同时发送 cookie 和身份验证标头,如下所示。

const url = "http://localhost:5000/stream"
//url is your server url

if ('EventSource' in window) {
  let source = new EventSource(url, {withCredentials: true})
}

Enter fullscreen mode Exit fullscreen mode

事件源对象事件

默认情况下,有三 (3) 个事件需要监听,包括消息打开错误。

  • 打开事件表示服务器和客户端之间已成功建立连接。

  • 错误事件处理服务器和客户端之间的连接错误

  • 消息事件用于监听服务器在成功连接后发出的实时流数据。

SSE 非常灵活,您甚至可以在服务器上定义自己的自定义事件,然后在客户端监听这些事件。

以下是三个(3)默认事件监听器及其回调函数。

source.addEventListener('message', function(e) {     
     console.log(e.data);
}, false);
Enter fullscreen mode Exit fullscreen mode
source.addEventListener('open', function(e) {
  // successful connection.
}, false);
Enter fullscreen mode Exit fullscreen mode
source.addEventListener('error', function(e) {
  // error occurred
}, false);
Enter fullscreen mode Exit fullscreen mode

EventSource 对象属性

EventSource实例的一些属性包括:

  • readyState例如 source.readyState

    • readyState 值为 0 表示正在连接
    • readyState 值为 1 表示打开
    • readyState 值为 0 表示已关闭
  • 例如source.url返回连接 URL

  • withCredentials例如 source.withCredentials 显示withCredentials是否为真。

EventSource 对象方法

可以调用closed ()方法来关闭连接,例如 source.closed()

服务器端实现

SSE 数据格式

服务器发送到浏览器的 SSE 数据必须是带有以下 HTTP 标头的 UTF-8 编码文本。

Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive
Enter fullscreen mode Exit fullscreen mode

每次发送的信息由若干条消息组成,每条消息之间用\n\n分隔。每条消息内部由多行代码组成,每行代码应按如下方式编写。

上述字段可以取以下四个值。

  • *数据*表示要发送的有效载荷。

  • 重试次数表示重新连接所需的时间(以秒为单位),此项为可选。

  • 事件可以是自定义事件,例如通知;如果没有传递事件,则默认为消息。

  • id表示要发送的数据的 ID,它是可选的。

const emitSSE= (res, id, data) =>{
  res.write('id: ' + id + '\n');
  res.write("data: " + data + '\n\n');
  res.flush()
}

const handleSSE = (req, res) =>{
  res.writeHead(200, {
    'Content-Type': 'text/event-stream',
    'Cache-Control': 'no-cache',
    'Connection': 'keep-alive'
  });
  const id = (new Date()).toLocaleTimeString();
  // Sends a SSE every 3 seconds on a single connection.
  setInterval(function() {
    emitSSE(res, id, (new Date()).toLocaleTimeString());
  }, 3000);

  emitSSE(res, id, (new Date()).toLocaleTimeString());
}



//use it

app.get("/stream", handleSSE)
Enter fullscreen mode Exit fullscreen mode

在 React.js 和 Node.js 中使用服务器发送事件

实现服务器发送事件相对简单,但当需要将事件定向或发送给特定用户时,就会变得复杂,因为目前还没有明确的方法与服务器交换用户数据。
不过,在下面的视频教程中,我们已经解决了发送全局事件以及定向特定用户的问题。

在下面的视频教程中,我们将从头开始,使用 react.js、node.js 和 mongodb,通过服务器发送事件 (SSE) 构建和部署一个类似 Twitter 的实时新闻源,并将其部署到 cPanel 上。

本教程面向希望学习如何实现以下功能的初学者和高级程序员:

  1. 如何在 React js 和 Node js 应用程序中实现 SSE
  2. 如何使用服务器发送事件将数据广播给所有用户
  3. 如何使用服务器发送事件将数据发送给特定用户或单个用户
  4. 如何实现“点赞”按钮
  5. API(应用程序编程接口)
  6. React Hooks(useState、useContext、useReducer)
  7. 在 cPanel 上进行托管(部署)

资源与演示

从 GitHub 获取代码

演示测试,点击此处查看。

您还可以阅读

流处理范式:实现连续数据分析和转换

概括

实时数据流已成为现代标准应用程序的必备功能,因为它能让用户随时了解应用程序中的所有活动。本文探讨了各种客户端-服务器通信技术,以及采用服务器发送事件 (SSE) 的必要性。服务器发送事件 (SSE) 是一种服务器推送技术,它允许客户端通过 HTTP 连接接收来自服务器的实时数据流更新。SSE 技术轻量级,并被大多数现代浏览器支持,因此非常适合用于从服务器发送实时自动数据流。

视频教程

如果你想观看并学习如何使用 React js 和 Node js 实现服务器发送事件 (SSE) 的深入教程,这里有一个视频供你观看。

请不要忘记点赞、评论、订阅我的YouTube频道,并将视频分享给你的朋友们。

文章来源:https://dev.to/torver213/realtime-data-streaming-using-server-sent-eventssse-with-reactjs-and-nodejs-2aak