前端 EventSource(SSE)实时通信使用指南(EventSource-polyfill)_eventsourcepolyfill
文章目录
- 前言
- 一、什么是 EventSource
- 二、与其他实时通信技术的对比
- 三、适用场景
-
- 1、 实时通知系统
- 2、实时数据监控与仪表盘
- 3、新闻与内容实时推送
- 4、物联网设备状态监控
- 5、协作工具实时状态同步
- 6、排队系统与预约通知
- 三、EventSource 核心用法与 API 详解
- 四、自定义请求头
-
- 方案 1:URL 参数法
- 方案 2:Cookie 认证法
- 方案 3:代理层注入
- 4、使用第三方库 eventsource-polyfill (推荐)
- 五、eventsource-polyfill(第三方库)
-
- 1、与EventSource比较
-
- (1) 浏览器兼容性
- 原生EventSource
- eventsource-polyfill 支持范围:
- (2) 突破原生 API 的功能限制
- 2、eventsource-polyfill使用
-
- 1、安装
- 2、使用
- (1)基础示例
- (2)自定义请求头
- (3) 自定义重连策略
- (4)post请求
- 总结
前言
在现代 Web 应用开发中,实现实时数据更新是提升用户体验的关键需求。EventSource 作为 HTML5 标准中定义的服务器推送技术,为前端开发者提供了一种轻量级、低功耗的实时通信解决方案。本文将从基础概念到实战应用,全面解析 EventSource 的使用方法。
一、什么是 EventSource
EventSource 是 HTML5 规范中定义的 API,它建立了从浏览器到服务器的单向持久连接,允许服务器主动向客户端推送事件数据,非常适合单向实时数据流场景。与传统的轮询(Polling)和 WebSocket 相比,EventSource 具有以下核心特性:
- 单向通信:仅支持服务器向客户端推送数据,适合新闻更新、通知提醒等场景
- 自动重连:连接断开时会自动尝试重连,无需手动处理断线逻辑
- 轻量级协议:基于 HTTP/HTTPS,使用简单的文本格式传输,开销低于 WebSocket
- 原生支持:浏览器内置实现,无需额外库依赖
二、与其他实时通信技术的对比
三、适用场景
1、 实时通知系统
社交平台新消息提醒、电商订单状态变更、系统公告推送
2、实时数据监控与仪表盘
服务器日志实时监控、系统性能指标(CPU / 内存)展示、股票行情更新
3、新闻与内容实时推送
新闻网站突发新闻推送、直播平台弹幕展示、社交媒体动态更新
4、物联网设备状态监控
智能家居设备状态(温度、湿度)实时显示、工业设备故障告警
5、协作工具实时状态同步
多人在线文档编辑(如飞书文档)的光标位置同步、在线用户状态显示
6、排队系统与预约通知
医院挂号排队进度、餐厅预约叫号、服务窗口等待通知
适用场景特征总结:
- 单向数据流动:数据仅从服务器流向客户端(如推送通知、更新状态)
- 实时性要求中等:秒级更新即可满足需求(非毫秒级高频交互)
- 服务器主动触发:事件由服务器端业务逻辑驱动(如数据变更、用户操作)
- 多客户端订阅:同一事件需要推送给多个客户端(如广播通知)
- 轻量级通信:数据格式简单(文本 / JSON),无需二进制传输
三、EventSource 核心用法与 API 详解
快速上手示例:
//创建实例,连接到服务器const eventSource = new EventSource(\'https://xxxxxxxxxx\');// 监听连接打开事件eventSource.onopen = function(event) { console.log(\'连接已建立:\', event);};// 监听消息推送eventSource.onmessage = (event) => { // event.data 包含服务器发送的文本数据 // 解析JSON数据示例 try { const data = JSON.parse(event.data); //可以在此处添加获取数据后的处理逻辑 } catch (error) { console.error(\'数据解析失败:\', error, event.data); }};// 错误处理(包含自动重连)eventSource.onerror = (event) => { if (event.readyState === EventSource.CLOSED) { console.log(\'连接已关闭\'); } };
关键API详解
1、创建实例
const source = new EventSource(url, configuration);
-
url:服务器端点地址
-
configuration :可选配置对象
{ withCredentials: true } // 跨域时携带凭据
2、事件监听
默认3种类型:
- onopen:连接建立时触发
- onerror:连接错误时触发
- onmessage:接收未指定事件类型的消息
上述事件也可以使用addEventListener方法代替:
// 监听连接打开事件eventSource.addEventListener(\'open\', (event) => { console.log(\'open\',event)});// 监听错误事件eventSource.addEventListener(\'error\', (event) => { console.log(\'error\',event)});// 监听消息推送eventSource.addEventListener(\'message\', (event) => { console.log(\'message\',event)});
3、连接管理
- close: 主动关闭连接
eventSource.close(); // 主动关闭连接
在页面卸载或组件销毁时记得调用
4、自定义事件与数据格式
服务器可以推送自定义类型的事件,前端通过事件类型区分不同的数据处理逻辑,自定义类型事件依然通过addEventListener监听
// 服务器推送的事件流返回数据(文本格式)// 自定义通知事件event: notificationdata: {\"title\":\"系统通知\",\"body\":\"您有新的订单\"}
// 监听自定义事件类型(由服务器定义)eventSource.addEventListener(\'notification\', (event) => { const notification = JSON.parse(event.data); // 这里添加显示通知的函数}, false);
5、 处理连接断开与异常情况
在实际应用中,需要完善的连接管理策略来处理各种异常情况,可采用指数退避重连策略。
// 最大重连间隔(毫秒)const maxReconnectInterval = 30000; // 30秒// 重连间隔增长因子let reconnectInterval = 1000; // 初始1秒function connect() { const source = new EventSource(\'/events\'); source.onerror = event => { if (event.target.readyState === EventSource.CLOSED) {// 连接已关闭,手动重连 source.close(); setTimeout(connect, reconnectInterval); reconnectInterval = Math.min(reconnectInterval * 2, maxReconnectInterval ); } }; source.onopen = () => { reconnectInterval = 1000; // 重置重连延迟 }; source.onmessage = function(event) { // 处理消息逻辑... };}connect();
指数退避重连策略就是连接失败后定时持续不断重连,每次请求时间间隔 通过指数增长减小请求频率,通过指数退避重连策略可以避免服务器故障雪崩,给服务端恢复时间,减少客户端与服务端无效流量,平衡实时性与设备资源消耗
四、自定义请求头
请求头设置Token是用户身份鉴权认证常用方式 ,EventSource 原生不支持设置自定义请求头,这是其设计上的一个显著限制。但通过巧妙的技术方案,我们可以绕过这个限制模拟实现自定义请求头功能。
实现可以采用以下方式:
方案 1:URL 参数法
const authToken = \'eyJhbGxxxxxxxxxxxxxxxx\';const eventSource = new EventSource(`/api/systemLog?token=${encodeURIComponent(authToken)}`);
// 服务器端解析示例 (Node.js)app.get(\'/api/systemLog\', (req, res) => { const token = req.query.token; if (!validateToken(token)) { res.status(401).end(); return; } res.setHeader(\'Content-Type\', \'text/event-stream\'); // ... SSE 实现});
通过URL拼接参数传递token
方案 2:Cookie 认证法
// 设置认证 Cookiedocument.cookie = `auth_token=${authToken}; path=/; SameSite=Lax; Secure`;// 创建 EventSourceconst eventSource = new EventSource(\'/api/systemLog\', { withCredentials: true // 携带凭据});
服务器配置:
Set-Cookie: auth_token=xyz; Path=/; HttpOnly; SameSite=LaxAccess-Control-Allow-Origin: https://yourdomain.comAccess-Control-Allow-Credentials: true
通过设置cookie传递,需要处理跨域配置
方案 3:代理层注入
使用 Nginx 或 API 网关注入请求头:
# nginx.conflocation /sse-proxy/ { proxy_pass http://xxxxxxx/api/systemLog; # 注入自定义头 proxy_set_header X-Client-ID $http_x_client_id; proxy_set_header Authorization \"Bearer your-static-token\"; proxy_buffering off; proxy_read_timeout 24h;}
客户端:
// 通过代理路径访问const eventSource = new EventSource(\'/sse-proxy/\');// 添加客户端 ID(作为普通头)const clientId = generateUUID();eventSource._xhr.setRequestHeader(\'X-Client-ID\', clientId);
企业级应用,复杂部署
4、使用第三方库 eventsource-polyfill (推荐)
见下章节介绍
五、eventsource-polyfill(第三方库)
EventSource-polyfill 是一个用于实现 EventSource 接口的 JavaScript 库,主要作用是为原生不支持该接口的浏览器提供兼容性解决方案,以及突破原生 API 的功能限制。推荐使用eventsource-polyfill来替代原生EventSource 。
1、与EventSource比较
(1) 浏览器兼容性
原生EventSource
- Internet Explorer(全版本)不支持
- Opera Mini(移动端)不支持
- 老版本 Safari(<12.1)存在部分支持问题
eventsource-polyfill 支持范围:
- IE 10+
- Edge 12+
- Firefox 3.5+
- Chrome 4+
- Safari 5+
- Opera 11.5+
- iOS Safari 4.2+
- Android Browser 3+
(2) 突破原生 API 的功能限制
2、eventsource-polyfill使用
1、安装
CDN引入
<script src=\"https://cdn.jsdelivr.net/npm/eventsource-polyfill/dist/eventsource.min.js\"></script>
或
npm安装
npm install eventsource-polyfill --save
导入模块
import { EventSourcePolyfill } from \'eventsource-polyfill\';
2、使用
Eventsource-polyfill完全遵循原生 EventSource 的 API 规范,因此使用方式也是类似
(1)基础示例
// 创建实例(与原生API一致)const eventSource = new EventSourcePolyfill(\'https://xxxxxxxx\');// 监听事件(同原生EventSource)eventSource.onopen = () => { console.log(\'连接已建立\');};eventSource.onmessage = (event) => { console.log(\'接收数据:\', event.data); // 解析JSON数据 try { const data = JSON.parse(event.data); //可以在此处添加获取数据后的处理逻辑 } catch (error) { console.error(\'数据解析失败\', error); }};eventSource.onerror = (event) => { console.log(\'连接错误\',event);};// 关闭连接// eventSource.close();
(2)自定义请求头
import { EventSourcePolyfill } from \'event-source-polyfill\';const eventSource = new EventSourcePolyfill(\'https://xxxxxxxx\', { headers: { \'Authorization\': \'eyJhbxxxxxxxxxxx...\',//设置token }, withCredentials: true // 携带跨域凭据});
(3) 自定义重连策略
const eventSource = new EventSourcePolyfill(\'https://xxxxxxxxx\', { heartbeatTimeout:30000, //重连时间间隔(ms) maxRetries: 10, // 最大重试次数 });
(4)post请求
// 发送 POST 请求带请求体const sse = new EventSourcePolyfill(\'https://xxxxxxxxx\', { method: \'POST\', body: JSON.stringify({ name: \'张三\', age:20 }), headers: { \'Content-Type\': \'application/json\' }});
小结:
使用eventsource-polyfill代替EventSource ,前端开发者可以在保持代码简洁的同时,解决原生 EventSource 的功能限制,为用户提供更稳定、更安全的实时通信体验。
总结
EventSource 作为轻量级服务器推送方案,以单向通信、自动重连等特性,在实时通知、数据监控等场景中提供了简洁高效的解决方案。尽管原生 API 存在请求头限制和兼容性问题,但通过代理服务器中转、eventsource-polyfill 等工具,可轻松突破限制并拓展功能。在实际开发中,合理选择 EventSource 与 WebSocket 等技术,结合业务场景优化重连策略与认证机制,便能为用户打造低功耗、高稳定性的实时交互体验 —— 这正是前端实时通信领域「轻量而不简单」的魅力所在。