马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
一、SSE是什么?
网络中的 SSE (Server-Sent Events) 是一种服务器向欣赏器单向推送数据的机制,常用于必要实时更新的数据传输,如消息推送、股票行情、谈天应用等。
SSE 的特点:
- 单向通讯:服务器向客户端推送数据,但客户端无法直接通过 SSE 发消息给服务器(客户端可通过其他方式如 HTTP 哀求与服务器通讯)。
- 基于 HTTP/1.1:SSE 使用 HTTP 协议传输,平静凡 HTTP 哀求兼容,不必要 WebSocket 的复杂握手过程。
- 自动重连:假如毗连克制,SSE 会自动实验重新毗连。
- 文本传输:SSE 重要用于传输文本数据,传输的数据格式通常为 UTF-8。
SSE 的实现示例
1. 服务器端 (Node.js 示例):
- const http = require('http');
- http.createServer((req, res) => {
- if (req.url === '/events') {
- res.writeHead(200, {
- 'Content-Type': 'text/event-stream',
- 'Cache-Control': 'no-cache',
- 'Connection': 'keep-alive',
- });
- setInterval(() => {
- res.write(`data: ${new Date().toLocaleTimeString()}\n\n`);
- }, 1000);
- }
- }).listen(3000, () => console.log('SSE server running on http://localhost:3000'));
复制代码 2. 客户端 (HTML + JavaScript 示例):
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>SSE Demo</title>
- </head>
- <body>
- <h1>Server-Sent Events Demo</h1>
- <div id="messages"></div>
- <script>
- const eventSource = new EventSource('/events');
-
- eventSource.onmessage = (event) => {
- const messages = document.getElementById('messages');
- messages.innerHTML += `<p>${event.data}</p>`;
- };
- eventSource.onerror = () => {
- console.error('Connection lost, retrying...');
- };
- </script>
- </body>
- </html>
复制代码 SSE 与 WebSocket 的对比:
特点SSEWebSocket通讯方向单向(服务器 → 客户端)双向(服务器 ↔ 客户端)协议HTTP/1.1自界说 WebSocket 协议数据格式文本(UTF-8)文本和二进制实用场景实时推送但不必要双向通讯的数据实时交互、必要双向通讯的场景毗连复杂度简朴,基于 HTTP 哀求复杂,必要握手过程 SSE 的实用场景:
- 消息推送:如订阅消息源的实时更新。
- 股票市场数据:实时行情推送。
- 实时关照体系:如 Web 上的关照或警报体系。
- 在线谈天(简朴版):单向消息通报,如谈天消息广播。
SSE 提供了一种轻量级办理方案,用于在某些应用场景下更换 WebSocket,特别是当仅需单向数据流时。
二、服务端推送的数据格式是什么样的?
在 Server-Sent Events (SSE) 中,服务器推送的数据格式是基于 文本格式 的特别结构,每条消息由多少字段构成,每个字段通过换行符(\n)分隔。服务器将这些数据一连传输给客户端,以下是常用的 SSE 数据格式结构。
SSE 消息格式:
SSE 消息的格式遵照以下结构:- data: <消息数据>
- id: <消息ID>
- event: <事件类型>
- retry: <自动重连时间>
复制代码
- 每条消息之间必要使用 两个换行符(\n\n)分隔。
- id 字段用于标记消息的 ID,便于客户端追踪和在重连时获取丢失的消息。
- data 是消息的重要内容,支持多行数据。
- event 用于标记事故范例(可选),客户端可基于差别事故范例处理惩罚消息。
- retry 指定客户端断开毗连后的重连隔断(以毫秒为单元),可选。
示例消息:
- data: Hello, World!
- id: 1
- event: message
- retry: 3000
- data: {"temperature": 25, "humidity": 60}
- id: 2
- data: 这是第二条消息
- id: 3
复制代码 上述消息发送了三次推送:
- 第一条为事故范例 message,数据为 “Hello, World!”。
- 第二条为 JSON 格式的气候数据。
- 第三条是中文文本。
服务端相应完备示例:
服务器端的相应头必须设置准确的 MIME 范例,以确保客户端可以大概准确剖析 SSE 流。
示例相应头:
- HTTP/1.1 200 OK
- Content-Type: text/event-stream
- Cache-Control: no-cache
- Connection: keep-alive
复制代码 示例数据流:
- data: Server time: 2024-10-24 14:00:00
- id: 101
- data: New stock price: AAPL 180.55
- id: 102
- event: customEvent
- data: Custom event message
- id: 103
- retry: 5000
复制代码
- 第一条推送表现服务器的时间。
- 第二条推送为股票代价更新。
- 第三条界说了一个自界说事故 customEvent。
- retry: 5000 指定客户端在断开毗连时应每 5 秒实验重连。
客户端吸取数据的示例:
event.data 是每个数据流的数据,而非完备的
每次服务端发送一条消息时,EventSource 会触发 onmessage 事故,此中包罗一条新的数据。- const eventSource = new EventSource('/events');
- // 默认消息事件处理
- eventSource.onmessage = (event) => {
- console.log('Message:', event.data);
- };
- // 处理自定义事件
- eventSource.addEventListener('customEvent', (event) => {
- console.log('Custom Event:', event.data);
- });
- // 错误处理
- eventSource.onerror = () => {
- console.error('Connection error, trying to reconnect...');
- };
复制代码 总结:
在 SSE 中,服务端的数据格式必须是 纯文本流,而且按照规范使用 data、id、event 等字段。每条消息以两个换行符(\n\n)分隔,确保客户端能准确剖析与展示。同时,SSE 的格式简朴而有用,恰当必要实时数据推送但不必要复杂双向通讯的场景。
三、前端如那里置惩罚一段一段的数据?
在 SSE(Server-Sent Events) 中,服务端会将数据以一段段的方式一连推送给客户端。前端必要通过事故监听器处理惩罚这些消息,将数据举行逐条吸取和展示。以下是如安在前端处理惩罚 SSE 分段数据 的具体步调。
前端处理惩罚 SSE 分段数据的步调
- 使用 EventSource 创建 SSE 毗连。
- 监听差别范例的事故(默认 message 事故或自界说事故)。
- 累积或渐渐更新数据(如拼接消息、实时更新 UI)。
- 错误处理惩罚:包管毗连断开时可以大概重连。
根本代码示例
- // 1. 创建 SSE 连接
- const eventSource = new EventSource('/events');
- // 2. 默认消息处理:逐条接收并展示
- eventSource.onmessage = (event) => {
- console.log('Received message:', event.data);
- appendDataToUI(event.data); // 自定义逻辑将数据展示到页面
- };
- // 3. 监听自定义事件
- eventSource.addEventListener('customEvent', (event) => {
- console.log('Custom Event:', event.data);
- });
- // 4. 错误处理:如断开连接时自动尝试重连
- eventSource.onerror = (error) => {
- console.error('Connection lost, retrying...', error);
- };
- // 5. 自定义函数:将数据添加到页面
- function appendDataToUI(data) {
- const messagesDiv = document.getElementById('messages');
- const newMessage = document.createElement('p');
- newMessage.textContent = data;
- messagesDiv.appendChild(newMessage);
- }
复制代码 展示逐条消息
HTML 页面结构:
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>SSE Example</title>
- </head>
- <body>
- <h1>SSE Data Stream</h1>
- <div id="messages"></div>
-
- <script src="sse-handler.js"></script> <!-- 引入前端逻辑 -->
- </body>
- </html>
复制代码 如那里置惩罚分段数据
方案 1:逐条处理惩罚和展示
每当服务器发送一条消息时,客户端就将它添加到页面中。- eventSource.onmessage = (event) => {
- appendDataToUI(event.data); // 实时将数据展示
- };
复制代码 方案 2:拼接消息(累积数据流)
假如服务端的消息是分段发送的,必要客户端在完备吸取后举行拼接。比方,假设服务端每次发送数据的一部门:- let accumulatedData = ''; // 用于拼接的全局变量
- eventSource.onmessage = (event) => {
- accumulatedData += event.data; // 累积数据
- if (event.data.endsWith('[END]')) { // 判断是否为完整数据
- appendDataToUI(accumulatedData);
- accumulatedData = ''; // 重置累积数据
- }
- };
复制代码 处理惩罚 JSON 数据
假如服务端推送的是 JSON 数据,必要在前端剖析后展示:- eventSource.onmessage = (event) => {
- try {
- const jsonData = JSON.parse(event.data);
- console.log('JSON Data:', jsonData);
- appendDataToUI(`User: ${jsonData.user}, Message: ${jsonData.message}`);
- } catch (error) {
- console.error('Invalid JSON:', event.data);
- }
- };
复制代码 处理惩罚自界说事故的场景
服务端发送差别范例的事故时,可以在前端通过 addEventListener 针对差别事故分别处理惩罚:- eventSource.addEventListener('news', (event) => {
- console.log('News:', event.data);
- appendDataToUI(`News: ${event.data}`);
- });
- eventSource.addEventListener('alert', (event) => {
- console.log('Alert:', event.data);
- alert(`Alert: ${event.data}`);
- });
复制代码 总结
- 在 SSE 前端处理惩罚 中,焦点是通过 EventSource 一连吸取服务器推送的消息,并根据必要逐条或累积处理惩罚数据。
- 可以监听默认事故(message)和自界说事故。
- 拼接数据 时要确保能准确判定命据竣事标记,克制数据繁芜。
- 通过 JSON 剖析 支持复杂数据格式。
SSE 恰当实时消息展示和数据推送的场景,比方谈天应用、消息推送等。这个方案相比 WebSocket 更轻量,恰当单向数据流的需求。
四、怎样实现实时渲染
要在前端实现实时渲染 SSE 推送的数据,可以将数据一边吸取一边更新到页面中。具体实现方式依赖于 HTML 和 JavaScript,通过 DOM 操纵 动态将数据插入到页面,并确保界面流通地表现最新内容。
SSE 实时渲染步调
- 吸取服务端的推送数据:使用 EventSource 监听差别事故。
- 更新 UI:吸取数据后,立刻更新页面元素(如消息列表)。
- 优化性能:对于频仍更新的情况,可以使用节流或假造列表技能,包管性能不受影响。
根本实现:实时渲染数据
HTML 结构
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Real-time SSE Rendering</title>
- <style>
- #messages {
- max-height: 300px;
- overflow-y: auto;
- border: 1px solid #ccc;
- padding: 10px;
- }
- p {
- margin: 5px 0;
- }
- </style>
- </head>
- <body>
- <h1>Real-time Messages</h1>
- <div id="messages"></div>
- <script src="script.js"></script> <!-- 引入 JavaScript -->
- </body>
- </html>
复制代码 JavaScript 实现:实时吸取和渲染
- // 创建 SSE 连接
- const eventSource = new EventSource('/events');
- // 获取 DOM 元素
- const messagesDiv = document.getElementById('messages');
- // 处理服务端默认推送的 message 事件
- eventSource.onmessage = (event) => {
- renderMessage(event.data);
- };
- // 将消息渲染到页面
- function renderMessage(message) {
- const newMessage = document.createElement('p');
- newMessage.textContent = message;
- messagesDiv.appendChild(newMessage);
- // 保持滚动条在底部(自动滚动)
- messagesDiv.scrollTop = messagesDiv.scrollHeight;
- }
- // 错误处理:连接丢失时显示提示
- eventSource.onerror = () => {
- renderMessage('Connection lost. Reconnecting...');
- };
复制代码 效果:
- 每当服务器推送新消息时,onmessage 会捕获并调用 renderMessage() 方法,将消息插入页面。
- 自动滚动到页面底部:当消息增长超出容器高度时,scrollTop 确保用户总是看到最新消息。
性能优化:节流处理惩罚
假如数据推送频率较高,直接更新 DOM 大概导致性能题目。可以使用节流(throttling),限定每秒的渲染次数。- let lastRenderTime = 0;
- function throttledRenderMessage(message) {
- const now = Date.now();
- if (now - lastRenderTime > 100) { // 限制每100ms渲染一次
- renderMessage(message);
- lastRenderTime = now;
- }
- }
- eventSource.onmessage = (event) => {
- throttledRenderMessage(event.data);
- };
复制代码 优化方式:假造列表(Virtual List)
当消息数据量非常大时,可以使用假造列表技能,只渲染可见地区内的数据。可以借助第三方库(如 react-window、virtual-scroller)或本身实现。
总结
通过上述代码,你可以实现基于 SSE 的实时数据渲染:
- 使用 EventSource 一连吸取服务端推送的数据。
- 动态更新 DOM,让页面实时表现最新内容。
- 使用 自动滚动 让用户始终看到最新消息。
- 针对高频数据,可以使用 节流 或 假造列表 优化性能。
这种方式非常恰当谈天应用、实时消息推送或日志 监控 体系的前端实现。
五、event.data
onmessage 是怎样工作的?
- 长毗连:EventSource 使用 HTTP 长毗连,服务器在毗连创建后不绝推送数据给客户端,而无需客户端频仍发起新的哀求。
- 实时监听:onmessage 事故会在服务器推送 每一条新消息 时被触发,将当前这条消息的数据通报给客户端。
- 增量推送:每次推送的数据独立存在,并不会覆盖之前的数据,而是逐条吸取。
工作机制示例
服务端推送(SSE)数据格式:
- data: {"temperature": 25, "unit": "C"}
- id: 1
- data: {"temperature": 26, "unit": "C"}
- id: 2
- data: {"message": "System OK"}
- id: 3
复制代码 前端监听新数据:
- // 建立 SSE 连接
- const eventSource = new EventSource('/events');
- // 每当服务器推送一条新数据时,onmessage 就会触发
- eventSource.onmessage = (event) => {
- console.log('Received new data:', event.data); // 打印当前推送的数据
- processData(event.data); // 处理新数据
- };
- // 自定义数据处理逻辑
- function processData(data) {
- const parsedData = JSON.parse(data);
- console.log('Parsed Data:', parsedData);
- // 在页面中展示数据或加入队列等操作
- }
复制代码 逐条处理惩罚新数据
每当服务器推送一条新数据时:
- onmessage 会自动触发,并返回当前这条推送的数据。
- 这是一种流式处理惩罚,即:每次推送的新数据都是单独处理惩罚的,不会覆盖或与之前的数据肴杂。
EventSource 数据流的特点
- 数据流:EventSource 是实时监听数据流变革,服务器每次发送新数据时,客户端会立刻捕获。
- 自动重连:假如毗连克制(如网络颠簸),EventSource 会实验自动重连,并从末了的消息 ID 开始吸取。
- 次序包管:EventSource 包管了数据的次序性,确保客户端按服务端的发送次序吸取数据。
怎样判定每条数据是否完备?
在某些情况下,假如数据分片发送(好比必要多个部门组合成一条完备消息),可以使用竣事标识(如 [END])来判定:
示例:拼接分片数据
- let accumulatedData = '';
- eventSource.onmessage = (event) => {
- accumulatedData += event.data; // 累积数据片段
- if (event.data.endsWith('[END]')) {
- console.log('Complete Data:', accumulatedData);
- processData(accumulatedData);
- accumulatedData = ''; // 重置累积数据
- }
- };
复制代码 总结
- onmessage 会在每次服务器推送一条新数据时被触发,event.data 包罗这条消息的内容。
- 数据流监听是实时的,客户端可以逐条吸取并处理惩罚新数据。
- 数据不会被覆盖,而是按服务端发送的次序逐条吸取。
- 可以根据必要对高频数据举行拼接、节流或批量处理惩罚,包管页面的性能和用户体验。
EventSource 是一种非常恰当实时数据推送(如谈天、日志 、监控 等)的轻量级方案。
|