关于sse、websocket与流式渲染

[复制链接]
发表于 2026-1-3 14:29:09 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
一、SSE是什么?

网络中的 SSE (Server-Sent Events) 是一种服务器向欣赏器单向推送数据的机制,常用于必要实时更新的数据传输,如消息推送、股票行情、谈天应用等。

SSE 的特点:


  • 单向通讯:服务器向客户端推送数据,但客户端无法直接通过 SSE 发消息给服务器(客户端可通过其他方式如 HTTP 哀求与服务器通讯)。
  • 基于 HTTP/1.1:SSE 使用 HTTP 协议传输,平静凡 HTTP 哀求兼容,不必要 WebSocket 的复杂握手过程。
  • 自动重连:假如毗连克制,SSE 会自动实验重新毗连。
  • 文本传输:SSE 重要用于传输文本数据,传输的数据格式通常为 UTF-8。

SSE 的实现示例

1. 服务器端 (Node.js 示例):
  1. const http = require('http');
  2. http.createServer((req, res) => {
  3.   if (req.url === '/events') {
  4.     res.writeHead(200, {
  5.       'Content-Type': 'text/event-stream',
  6.       'Cache-Control': 'no-cache',
  7.       'Connection': 'keep-alive',
  8.     });
  9.     setInterval(() => {
  10.       res.write(`data: ${new Date().toLocaleTimeString()}\n\n`);
  11.     }, 1000);
  12.   }
  13. }).listen(3000, () => console.log('SSE server running on http://localhost:3000'));
复制代码
2. 客户端 (HTML + JavaScript 示例):
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4.   <meta charset="UTF-8">
  5.   <title>SSE Demo</title>
  6. </head>
  7. <body>
  8.   <h1>Server-Sent Events Demo</h1>
  9.   <div id="messages"></div>
  10.   <script>
  11.     const eventSource = new EventSource('/events');
  12.    
  13.     eventSource.onmessage = (event) => {
  14.       const messages = document.getElementById('messages');
  15.       messages.innerHTML += `<p>${event.data}</p>`;
  16.     };
  17.     eventSource.onerror = () => {
  18.       console.error('Connection lost, retrying...');
  19.     };
  20.   </script>
  21. </body>
  22. </html>
复制代码

SSE 与 WebSocket 的对比:

特点SSEWebSocket通讯方向单向(服务器 → 客户端)双向(服务器 ↔ 客户端)协议HTTP/1.1自界说 WebSocket 协议数据格式文本(UTF-8)文本和二进制实用场景实时推送但不必要双向通讯的数据实时交互、必要双向通讯的场景毗连复杂度简朴,基于 HTTP 哀求复杂,必要握手过程
SSE 的实用场景:


  • 消息推送:如订阅消息源的实时更新。
  • 股票市场数据:实时行情推送。
  • 实时关照体系:如 Web 上的关照或警报体系。
  • 在线谈天(简朴版):单向消息通报,如谈天消息广播。
SSE 提供了一种轻量级办理方案,用于在某些应用场景下更换 WebSocket,特别是当仅需单向数据流时。
二、服务端推送的数据格式是什么样的?

在 Server-Sent Events (SSE) 中,服务器推送的数据格式是基于 文本格式 的特别结构,每条消息由多少字段构成,每个字段通过换行符(\n)分隔。服务器将这些数据一连传输给客户端,以下是常用的 SSE 数据格式结构。

SSE 消息格式:

SSE 消息的格式遵照以下结构:
  1. data: <消息数据>
  2. id: <消息ID>
  3. event: <事件类型>
  4. retry: <自动重连时间>
复制代码

  • 每条消息之间必要使用 两个换行符(\n\n)分隔。
  • id 字段用于标记消息的 ID,便于客户端追踪和在重连时获取丢失的消息。
  • data 是消息的重要内容,支持多行数据。
  • event 用于标记事故范例(可选),客户端可基于差别事故范例处理惩罚消息。
  • retry 指定客户端断开毗连后的重连隔断(以毫秒为单元),可选。

示例消息:
  1. data: Hello, World!
  2. id: 1
  3. event: message
  4. retry: 3000
  5. data: {"temperature": 25, "humidity": 60}
  6. id: 2
  7. data: 这是第二条消息
  8. id: 3
复制代码
上述消息发送了三次推送:

  • 第一条为事故范例 message,数据为 “Hello, World!”。
  • 第二条为 JSON 格式的气候数据。
  • 第三条是中文文本。

服务端相应完备示例:

服务器端的相应头必须设置准确的 MIME 范例,以确保客户端可以大概准确剖析 SSE 流。
示例相应头:
  1. HTTP/1.1 200 OK
  2. Content-Type: text/event-stream
  3. Cache-Control: no-cache
  4. Connection: keep-alive
复制代码
示例数据流:
  1. data: Server time: 2024-10-24 14:00:00
  2. id: 101
  3. data: New stock price: AAPL 180.55
  4. id: 102
  5. event: customEvent
  6. data: Custom event message
  7. id: 103
  8. retry: 5000
复制代码

  • 第一条推送表现服务器的时间。
  • 第二条推送为股票代价更新。
  • 第三条界说了一个自界说事故 customEvent。
  • retry: 5000 指定客户端在断开毗连时应每 5 秒实验重连。

客户端吸取数据的示例:

event.data 是每个数据流的数据,而非完备的
每次服务端发送一条消息时,EventSource 会触发 onmessage 事故,此中包罗一条新的数据。
  1. const eventSource = new EventSource('/events');
  2. // 默认消息事件处理
  3. eventSource.onmessage = (event) => {
  4.   console.log('Message:', event.data);
  5. };
  6. // 处理自定义事件
  7. eventSource.addEventListener('customEvent', (event) => {
  8.   console.log('Custom Event:', event.data);
  9. });
  10. // 错误处理
  11. eventSource.onerror = () => {
  12.   console.error('Connection error, trying to reconnect...');
  13. };
复制代码

总结:

在 SSE 中,服务端的数据格式必须是 纯文本流,而且按照规范使用 data、id、event 等字段。每条消息以两个换行符(\n\n)分隔,确保客户端能准确剖析与展示。同时,SSE 的格式简朴而有用,恰当必要实时数据推送但不必要复杂双向通讯的场景。
三、前端如那里置惩罚一段一段的数据?

在 SSE(Server-Sent Events) 中,服务端会将数据以一段段的方式一连推送给客户端。前端必要通过事故监听器处理惩罚这些消息,将数据举行逐条吸取和展示。以下是如安在前端处理惩罚 SSE 分段数据 的具体步调。

前端处理惩罚 SSE 分段数据的步调


  • 使用 EventSource 创建 SSE 毗连。
  • 监听差别范例的事故(默认 message 事故或自界说事故)。
  • 累积或渐渐更新数据(如拼接消息、实时更新 UI)。
  • 错误处理惩罚:包管毗连断开时可以大概重连。

根本代码示例
  1. // 1. 创建 SSE 连接
  2. const eventSource = new EventSource('/events');
  3. // 2. 默认消息处理:逐条接收并展示
  4. eventSource.onmessage = (event) => {
  5.   console.log('Received message:', event.data);
  6.   appendDataToUI(event.data);  // 自定义逻辑将数据展示到页面
  7. };
  8. // 3. 监听自定义事件
  9. eventSource.addEventListener('customEvent', (event) => {
  10.   console.log('Custom Event:', event.data);
  11. });
  12. // 4. 错误处理:如断开连接时自动尝试重连
  13. eventSource.onerror = (error) => {
  14.   console.error('Connection lost, retrying...', error);
  15. };
  16. // 5. 自定义函数:将数据添加到页面
  17. function appendDataToUI(data) {
  18.   const messagesDiv = document.getElementById('messages');
  19.   const newMessage = document.createElement('p');
  20.   newMessage.textContent = data;
  21.   messagesDiv.appendChild(newMessage);
  22. }
复制代码

展示逐条消息

HTML 页面结构:
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4.   <meta charset="UTF-8">
  5.   <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6.   <title>SSE Example</title>
  7. </head>
  8. <body>
  9.   <h1>SSE Data Stream</h1>
  10.   <div id="messages"></div>
  11.   
  12.   <script src="sse-handler.js"></script> <!-- 引入前端逻辑 -->
  13. </body>
  14. </html>
复制代码

如那里置惩罚分段数据

方案 1:逐条处理惩罚和展示

每当服务器发送一条消息时,客户端就将它添加到页面中。
  1. eventSource.onmessage = (event) => {
  2.   appendDataToUI(event.data);  // 实时将数据展示
  3. };
复制代码
方案 2:拼接消息(累积数据流)

假如服务端的消息是分段发送的,必要客户端在完备吸取后举行拼接。比方,假设服务端每次发送数据的一部门:
  1. let accumulatedData = '';  // 用于拼接的全局变量
  2. eventSource.onmessage = (event) => {
  3.   accumulatedData += event.data;  // 累积数据
  4.   if (event.data.endsWith('[END]')) {  // 判断是否为完整数据
  5.     appendDataToUI(accumulatedData);
  6.     accumulatedData = '';  // 重置累积数据
  7.   }
  8. };
复制代码

处理惩罚 JSON 数据

假如服务端推送的是 JSON 数据,必要在前端剖析后展示:
  1. eventSource.onmessage = (event) => {
  2.   try {
  3.     const jsonData = JSON.parse(event.data);
  4.     console.log('JSON Data:', jsonData);
  5.     appendDataToUI(`User: ${jsonData.user}, Message: ${jsonData.message}`);
  6.   } catch (error) {
  7.     console.error('Invalid JSON:', event.data);
  8.   }
  9. };
复制代码

处理惩罚自界说事故的场景

服务端发送差别范例的事故时,可以在前端通过 addEventListener 针对差别事故分别处理惩罚:
  1. eventSource.addEventListener('news', (event) => {
  2.   console.log('News:', event.data);
  3.   appendDataToUI(`News: ${event.data}`);
  4. });
  5. eventSource.addEventListener('alert', (event) => {
  6.   console.log('Alert:', event.data);
  7.   alert(`Alert: ${event.data}`);
  8. });
复制代码

总结


  • 在 SSE 前端处理惩罚 中,焦点是通过 EventSource 一连吸取服务器推送的消息,并根据必要逐条或累积处理惩罚数据。
  • 可以监听默认事故(message)和自界说事故。
  • 拼接数据 时要确保能准确判定命据竣事标记,克制数据繁芜。
  • 通过 JSON 剖析 支持复杂数据格式。
SSE 恰当实时消息展示和数据推送的场景,比方谈天应用、消息推送等。这个方案相比 WebSocket 更轻量,恰当单向数据流的需求。
四、怎样实现实时渲染

要在前端实现实时渲染 SSE 推送的数据,可以将数据一边吸取一边更新到页面中。具体实现方式依赖于 HTML 和 JavaScript,通过 DOM 操纵 动态将数据插入到页面,并确保界面流通地表现最新内容。

SSE 实时渲染步调


  • 吸取服务端的推送数据:使用 EventSource 监听差别事故。
  • 更新 UI:吸取数据后,立刻更新页面元素(如消息列表)。
  • 优化性能:对于频仍更新的情况,可以使用节流或假造列表技能,包管性能不受影响。

根本实现:实时渲染数据

HTML 结构
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4.   <meta charset="UTF-8">
  5.   <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6.   <title>Real-time SSE Rendering</title>
  7.   <style>
  8.     #messages {
  9.       max-height: 300px;
  10.       overflow-y: auto;
  11.       border: 1px solid #ccc;
  12.       padding: 10px;
  13.     }
  14.     p {
  15.       margin: 5px 0;
  16.     }
  17.   </style>
  18. </head>
  19. <body>
  20.   <h1>Real-time Messages</h1>
  21.   <div id="messages"></div>
  22.   <script src="script.js"></script> <!-- 引入 JavaScript -->
  23. </body>
  24. </html>
复制代码

JavaScript 实现:实时吸取和渲染
  1. // 创建 SSE 连接
  2. const eventSource = new EventSource('/events');
  3. // 获取 DOM 元素
  4. const messagesDiv = document.getElementById('messages');
  5. // 处理服务端默认推送的 message 事件
  6. eventSource.onmessage = (event) => {
  7.   renderMessage(event.data);
  8. };
  9. // 将消息渲染到页面
  10. function renderMessage(message) {
  11.   const newMessage = document.createElement('p');
  12.   newMessage.textContent = message;
  13.   messagesDiv.appendChild(newMessage);
  14.   // 保持滚动条在底部(自动滚动)
  15.   messagesDiv.scrollTop = messagesDiv.scrollHeight;
  16. }
  17. // 错误处理:连接丢失时显示提示
  18. eventSource.onerror = () => {
  19.   renderMessage('Connection lost. Reconnecting...');
  20. };
复制代码

效果:


  • 每当服务器推送新消息时,onmessage 会捕获并调用 renderMessage() 方法,将消息插入页面。
  • 自动滚动到页面底部:当消息增长超出容器高度时,scrollTop 确保用户总是看到最新消息。

性能优化:节流处理惩罚

假如数据推送频率较高,直接更新 DOM 大概导致性能题目。可以使用节流(throttling),限定每秒的渲染次数。
  1. let lastRenderTime = 0;
  2. function throttledRenderMessage(message) {
  3.   const now = Date.now();
  4.   if (now - lastRenderTime > 100) { // 限制每100ms渲染一次
  5.     renderMessage(message);
  6.     lastRenderTime = now;
  7.   }
  8. }
  9. eventSource.onmessage = (event) => {
  10.   throttledRenderMessage(event.data);
  11. };
复制代码

优化方式:假造列表(Virtual List)

当消息数据量非常大时,可以使用假造列表技能,只渲染可见地区内的数据。可以借助第三方库(如 react-window、virtual-scroller)或本身实现。

总结

通过上述代码,你可以实现基于 SSE 的实时数据渲染:

  • 使用 EventSource 一连吸取服务端推送的数据。
  • 动态更新 DOM,让页面实时表现最新内容。
  • 使用 自动滚动 让用户始终看到最新消息。
  • 针对高频数据,可以使用 节流 或 假造列表 优化性能。
这种方式非常恰当谈天应用、实时消息推送或日志日志监控监控体系的前端实现。
五、event.data

onmessage 是怎样工作的?


  • 长毗连:EventSource 使用 HTTP 长毗连,服务器在毗连创建后不绝推送数据给客户端,而无需客户端频仍发起新的哀求。
  • 实时监听:onmessage 事故会在服务器推送 每一条新消息 时被触发,将当前这条消息的数据通报给客户端。
  • 增量推送:每次推送的数据独立存在,并不会覆盖之前的数据,而是逐条吸取。

工作机制示例

服务端推送(SSE)数据格式:
  1. data: {"temperature": 25, "unit": "C"}
  2. id: 1
  3. data: {"temperature": 26, "unit": "C"}
  4. id: 2
  5. data: {"message": "System OK"}
  6. id: 3
复制代码
前端监听新数据:
  1. // 建立 SSE 连接
  2. const eventSource = new EventSource('/events');
  3. // 每当服务器推送一条新数据时,onmessage 就会触发
  4. eventSource.onmessage = (event) => {
  5.   console.log('Received new data:', event.data);  // 打印当前推送的数据
  6.   processData(event.data);  // 处理新数据
  7. };
  8. // 自定义数据处理逻辑
  9. function processData(data) {
  10.   const parsedData = JSON.parse(data);
  11.   console.log('Parsed Data:', parsedData);
  12.   // 在页面中展示数据或加入队列等操作
  13. }
复制代码

逐条处理惩罚新数据

每当服务器推送一条新数据时:

  • onmessage 会自动触发,并返回当前这条推送的数据。
  • 这是一种流式处理惩罚,即:每次推送的新数据都是单独处理惩罚的,不会覆盖或与之前的数据肴杂。

EventSource 数据流的特点


  • 数据流:EventSource 是实时监听数据流变革,服务器每次发送新数据时,客户端会立刻捕获。
  • 自动重连:假如毗连克制(如网络颠簸),EventSource 会实验自动重连,并从末了的消息 ID 开始吸取。
  • 次序包管:EventSource 包管了数据的次序性,确保客户端按服务端的发送次序吸取数据。

怎样判定每条数据是否完备?

在某些情况下,假如数据分片发送(好比必要多个部门组合成一条完备消息),可以使用竣事标识(如 [END])来判定:
示例:拼接分片数据
  1. let accumulatedData = '';
  2. eventSource.onmessage = (event) => {
  3.   accumulatedData += event.data;  // 累积数据片段
  4.   if (event.data.endsWith('[END]')) {
  5.     console.log('Complete Data:', accumulatedData);
  6.     processData(accumulatedData);
  7.     accumulatedData = '';  // 重置累积数据
  8.   }
  9. };
复制代码

总结


  • onmessage 会在每次服务器推送一条新数据时被触发,event.data 包罗这条消息的内容。
  • 数据流监听是实时的,客户端可以逐条吸取并处理惩罚新数据。
  • 数据不会被覆盖,而是按服务端发送的次序逐条吸取。
  • 可以根据必要对高频数据举行拼接、节流或批量处理惩罚,包管页面的性能和用户体验。
EventSource 是一种非常恰当实时数据推送(如谈天、日志日志、监控监控等)的轻量级方案。
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表