跳转到内容

JavaScript Server-Sent Events

来自代码酷

模板:编程学习导航

Server-Sent Events (SSE) 是一种基于 HTTP 的轻量级协议,允许服务器向客户端单向推送实时数据。与 WebSocket 不同,SSE 仅支持服务器到客户端的单向通信,但实现简单且兼容标准 HTTP 协议。

概述[编辑 | 编辑源代码]

SSE 通过持久的 HTTP 连接实现服务器推送,适用于需要实时更新但无需客户端频繁发送数据的场景(如新闻推送、股票行情、日志监控等)。

核心特性[编辑 | 编辑源代码]

  • 单向通信:服务器 → 客户端
  • 文本协议:基于纯文本(如 JSON、XML)
  • 自动重连:客户端在连接断开时会尝试重新连接
  • 事件流格式:遵循 `text/event-stream` MIME 类型

基本用法[编辑 | 编辑源代码]

客户端实现[编辑 | 编辑源代码]

使用 JavaScript 的 `EventSource` API 监听服务器事件:

  
// 创建 EventSource 对象,指定服务器端点  
const eventSource = new EventSource('/sse-endpoint');  

// 监听默认事件(未命名事件)  
eventSource.onmessage = (event) => {  
    console.log('收到数据:', event.data);  
};  

// 监听自定义事件  
eventSource.addEventListener('update', (event) => {  
    console.log('自定义事件数据:', event.data);  
});  

// 错误处理  
eventSource.onerror = (error) => {  
    console.error('SSE 错误:', error);  
};

服务器实现(Node.js 示例)[编辑 | 编辑源代码]

使用 Express 框架返回 `text/event-stream` 响应:

  
const express = require('express');  
const app = express();  

app.get('/sse-endpoint', (req, res) => {  
    // 设置响应头  
    res.setHeader('Content-Type', 'text/event-stream');  
    res.setHeader('Cache-Control', 'no-cache');  
    res.setHeader('Connection', 'keep-alive');  

    // 每秒发送一次数据  
    let counter = 0;  
    const interval = setInterval(() => {  
        counter++;  
        // 发送未命名事件  
        res.write(`data: ${JSON.stringify({ time: new Date(), count: counter })}\n\n`);  

        // 发送自定义事件  
        if (counter % 3 === 0) {  
            res.write(`event: update\ndata: ${counter}\n\n`);  
        }  
    }, 1000);  

    // 客户端断开连接时清理  
    req.on('close', () => clearInterval(interval));  
});  

app.listen(3000);

输出示例[编辑 | 编辑源代码]

客户端控制台将显示:

  
收到数据: {"time":"2023-10-01T12:00:01.000Z","count":1}  
收到数据: {"time":"2023-10-01T12:00:02.000Z","count":2}  
自定义事件数据: 3  

协议细节[编辑 | 编辑源代码]

事件流格式[编辑 | 编辑源代码]

每条消息由以下字段组成(字段间用 `\n` 分隔):

  • data:有效载荷(可多行)
  • event:自定义事件类型(可选)
  • id:事件 ID(用于断线重连)
  • retry:重连延迟(毫秒)

示例:

  
event: notification  
data: {"user": "Alice", "action": "login"}  
id: 42  
retry: 5000  

Mermaid 流程图[编辑 | 编辑源代码]

sequenceDiagram participant Client participant Server Client->>Server: GET /sse-endpoint (Accept: text/event-stream) Server-->>Client: HTTP 200 (Content-Type: text/event-stream) loop 持续推送 Server-->>Client: data: {...}\n\n end Client->>Server: 断开连接

实际案例[编辑 | 编辑源代码]

实时日志监控[编辑 | 编辑源代码]

场景:开发者在控制台查看服务器日志流。

  
// 客户端  
const logSource = new EventSource('/logs');  
logSource.onmessage = (event) => {  
    document.getElementById('log-output').innerHTML += event.data + '<br>';  
};  

// 服务器(Node.js)  
app.get('/logs', (req, res) => {  
    res.setHeader('Content-Type', 'text/event-stream');  
    const logStream = fs.createReadStream('app.log');  
    logStream.on('data', (chunk) => res.write(`data: ${chunk}\n\n`));  
});

数学公式支持[编辑 | 编辑源代码]

SSE 的带宽效率(假设无压缩)可表示为: E=有效数据总传输量=DD+H 其中 D 为数据大小,H 为协议头开销。

注意事项[编辑 | 编辑源代码]

  • 跨域问题:需配置 CORS(如 `Access-Control-Allow-Origin`)
  • 性能限制:单个浏览器最多允许 6 个 SSE 连接
  • 协议选择:高频双向通信建议使用 WebSocket

参见[编辑 | 编辑源代码]

模板:JavaScript 网络请求