微信小程序中基于 SSE 实现轻量级实时通讯 —— 原理、实践与对比分析_微信小程序 sse
本文系统梳理了在微信小程序开发中,如何使用 SSE(Server-Sent Events)方式实现轻量级即时通讯,结合实际项目实践,详细讲解原理、实现流程、对比 WebSocket/TCP/UDP 通讯方式,并给出完整模块封装与最佳实践建议。
文章目录
-
- 前言
- 一、微信小程序常见通讯方式概览
- 二、什么是 SSE(Server-Sent Events)?
- 三、为什么在小程序中选择 SSE?
- 四、小程序内使用 SSE 的完整实现
-
- 核心思路
- 五、详细代码示例(完整可用)
-
- 封装 SSE 模块
- 页面中使用示例
- 六、SSE 与 WebSocket/TCP/UDP 的对比分析
- 七、常见问题与优化策略
-
- 1. 短时间内多次重连?
- 2. 后台挂起导致连接断开?
- 3. 数据粘包、拆包问题?
- 八、总结
前言
在微信小程序开发中,很多业务场景需要与服务器保持准实时的通讯,例如:
- 消息通知
- 会议系统指令下发
- 任务状态推送
- 系统报警等
常规思路是使用 WebSocket,但小程序环境受限、项目复杂度、实时性需求不同,**SSE(Server-Sent Events)**成为一个非常优秀的轻量级替代方案。
一、微信小程序常见通讯方式概览
✅ 小程序原生支持 WebSocket,但 WebSocket 需要更高的资源管理。
✅ TCP/UDP 通常需要小程序插件权限,不适合普通业务。
二、什么是 SSE(Server-Sent Events)?
SSE(服务器发送事件) 是一种基于 HTTP 协议的推送机制,特点是:
- 单向通信:服务器主动向客户端推送数据
- 复用 HTTP 连接:不需要建立新的专用连接
- 轻量、低开销:比 WebSocket 简单很多
- 天生兼容 HTTP 基础设施
典型数据格式:
event: messagedata: {\"text\": \"新消息来了\"}
浏览器原生支持 EventSource
对象,但微信小程序没有,于是我们自己封装实现了 SSE 的效果。
三、为什么在小程序中选择 SSE?
选择理由:
- ✅ 小程序限制了后台长连接数量(尤其在安卓后台挂起时),SSE更友好
- ✅ HTTP长连接原生支持,兼容性好
- ✅ 不需要复杂的心跳机制,断线重连简单
- ✅ 轻量高效,适合中小量级的推送场景
典型业务适配场景:
- 会议系统指令推送
- 简单聊天系统消息提醒
- 系统公告推送
- 后台事件通知
四、小程序内使用 SSE 的完整实现
核心思路
1. 使用 wx.request 发起连接2. 设置 enableChunked = true 开启分片接收3. 监听 requestTask.onChunkReceived,实时接收数据4. 自行解析服务器推送的 text/event-stream 格式5. 断开后自动重连
五、详细代码示例(完整可用)
封装 SSE 模块
// utils/eventsource.tsimport EventBus from \'@/utils/eventBus\';export default class EventSourceClient { private url: string; private requestTask: WechatMiniprogram.RequestTask | null = null; private reconnectDelay = 5000; // 断线重连时间 private stopped = false; constructor(url: string) { this.url = url; } connect() { this.stopped = false; const token = wx.getStorageSync(\'token\') || \'\'; const headers: any = { \'Authorization\': `Bearer ${token}`, \'Accept\': \'text/event-stream\', \'Cache-Control\': \'no-cache\', \'Connection\': \'keep-alive\', }; this.requestTask = wx.request({ url: this.url, method: \'GET\', enableChunked: true, header: headers, timeout: 300000, success: () => {}, fail: (err) => { console.error(\'SSE连接失败:\', err); }, complete: () => { if (!this.stopped) { console.log(\'SSE断开,准备重连...\'); setTimeout(() => this.connect(), this.reconnectDelay); } }, }); this.requestTask.onChunkReceived((res) => { const uint8Array = new Uint8Array(res.data as ArrayBuffer); const text = this.uint8ArrayToString(uint8Array); this.handleSSEMessage(text); }); } private handleSSEMessage(text: string) { const messages = text.split(\'\'); messages.forEach((msg) => { const dataIndex = msg.indexOf(\'data:\'); if (dataIndex !== -1) { const jsonStr = msg.substring(dataIndex + 5).trim(); try { const data = JSON.parse(jsonStr); EventBus.emit(\'sse-message\', data); // 统一广播出去 } catch (e) { console.error(\'解析SSE消息失败\', e); } } }); } private uint8ArrayToString(u8Arr: Uint8Array): string { return String.fromCharCode.apply(null, Array.from(u8Arr)); } disconnect() { this.stopped = true; if (this.requestTask) { this.requestTask.abort(); this.requestTask = null; } }}
页面中使用示例
// pages/index/index.tsimport EventSourceClient from \'@/utils/eventsource\';let sseClient: EventSourceClient | null = null;Page({ onLoad() { sseClient = new EventSourceClient(\'https://your.api.com/events\'); sseClient.connect(); EventBus.on(\'sse-message\', this.handleSseMessage); }, onUnload() { if (sseClient) { sseClient.disconnect(); } EventBus.off(\'sse-message\', this.handleSseMessage); }, handleSseMessage(data: any) { console.log(\'收到服务器推送消息:\', data); // 处理逻辑 },});
六、SSE 与 WebSocket/TCP/UDP 的对比分析
七、常见问题与优化策略
1. 短时间内多次重连?
✅ 加入重连间隔限制(如 5秒后再连)
✅ 超过最大重试次数时提示用户
2. 后台挂起导致连接断开?
✅ 在 onShow
页面生命周期重新 connect
✅ 小程序后台挂起时停止轮询,降低资源消耗
3. 数据粘包、拆包问题?
✅ 服务器端推送规范化,每条消息完整 `
结束 ✅ 客户端按
` 分段处理
八、总结
微信小程序虽然原生提供了 WebSocket,但在很多中小体量、轻量实时推送场景下,
采用基于 wx.request
+ enableChunked
+ onChunkReceived
自行实现的 SSE 客户端,
是一种极为合理且高效的实时通讯方案。
这种方案不仅兼容性好、开发简单,还能极大地降低服务器与客户端的复杂度。
在未来如果业务体量增长,也可以平滑升级为 WebSocket,不影响前期投入。
✅ 简单、轻量、优雅,是这套方案最大的优势!
推荐实践:小程序轻量推送优先考虑 SSE,自由双向通讯则采用 WebSocket!