Fetch+ReadableStream可替代EventSource,解决其无法携带鉴权头、仅支持GET、难传复杂参数等痛点,通过手动解析text/event-stream流实现安全可控的SSE通信。

直接用 fetch 搭配 ReadableStream 实现 SSE,是解决原生 EventSource 无法携带鉴权头、不支持 POST、难传复杂参数等痛点的主流方案。它不依赖额外库,浏览器兼容性好(Chrome/Firefox/Safari 均支持),且能完全复用你已有的 token 管理逻辑。
为什么 EventSource 不适合带鉴权的真实项目
原生 EventSource 只接受 URL 字符串,不支持传入 headers 或 body:
- JWT 鉴权只能靠 URL 拼接(
/sse?token=xxx),暴露在浏览器历史、代理日志、CDN 缓存中,存在安全风险 - 无法使用
Cookie+SameSite配合的会话体系,尤其当前端与后端跨域时更难对齐 - 想传行情订阅列表
{symbols: ["BTC-USDT"], interval: "1s"},只能编码进 query,字段一多就易出错、难维护
Fetch + ReadableStream 的核心实现步骤
本质是手动解析服务端返回的 text/event-stream 数据流。关键四步:
- 调用
fetch(url, { method, headers, body })发起请求,确保响应头含Content-Type: text/event-stream - 从
response.body获取ReadableStream,用getReader()创建读取器 - 用
TextDecoder将二进制块转为字符串,按\n\n分割消息,再逐行解析data:、event:、id:等字段 - 每收到一条完整消息,触发回调(如
onMessage(data)),并可依据id和retry实现可控重连
如何安全复用你的 Token 管理逻辑
不要每次请求都拼字符串,而是复用一个可变的 Headers 实例:
- 全局创建
const authHeaders = new Headers(),封装setToken(token)方法,内部调用authHeaders.set('Authorization', 'Bearer ' + token) - 发起 SSE 请求时,直接传
{ headers: authHeaders };如需额外头(如Content-Type),可新建const reqHeaders = new Headers(authHeaders)后追加 - 401 响应或 token 过期时,调用
clearToken()并触发登录流程,后续请求自动带上新凭证
一个轻量可用的封装示例(Vue3 Composition API)
你可以将其封装为 useSSE(url, { onMessage, onError, onOpen, token }):
- 内部自动注入
Authorization头,支持动态更新 - 连接建立后触发
onOpen,每条data:消息解析为 JSON 后调用onMessage - 网络中断或服务端关闭时,提供
retry: 3000重试策略,也可交由上层控制 - 暴露
close()方法,便于组件卸载时主动断开连接,避免内存泄漏

















