本文系统梳理了在微信小程序开发中,如何使用 SSE(Server-Sent Events)方式实现轻量级即时通讯,结合实际项目实践,详细讲解原理、实现流程、对比 WebSocket/TCP/UDP 通讯方式,并给出完整模块封装与最佳实践建议。
在微信小程序开发中,很多业务场景需要与服务器保持准实时的通讯,例如:
常规思路是使用 WebSocket,但小程序环境受限、项目复杂度、实时性需求不同,**SSE(Server-Sent Events)**成为一个非常优秀的轻量级替代方案。
通讯方式 | 特点 | 适用场景 |
---|---|---|
HTTP Request | 无状态、短连接 | 普通数据交互 |
WebSocket | 长连接、双向通信 | 聊天、实时协作、游戏 |
TCP Socket | 底层高性能 | 小程序插件环境、直播等 |
UDP | 无连接、快速 | 一般用于局域网插件,不常用于小程序主流业务 |
SSE | 单向推送、长连接、轻量实现 | 轻量级推送、低频实时更新 |
✅ 小程序原生支持 WebSocket,但 WebSocket 需要更高的资源管理。
✅ TCP/UDP 通常需要小程序插件权限,不适合普通业务。
SSE(服务器发送事件) 是一种基于 HTTP 协议的推送机制,特点是:
典型数据格式:
event: message
data: {"text": "新消息来了"}
浏览器原生支持 EventSource
对象,但微信小程序没有,于是我们自己封装实现了 SSE 的效果。
选择理由:
典型业务适配场景:
1. 使用 wx.request 发起连接
2. 设置 enableChunked = true 开启分片接收
3. 监听 requestTask.onChunkReceived,实时接收数据
4. 自行解析服务器推送的 text/event-stream 格式
5. 断开后自动重连
// utils/eventsource.ts
import 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.ts
import 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 |
---|---|---|---|---|
连接方式 | HTTP长连接 | 专用协议 | 低层连接 | 无连接 |
通讯方向 | 单向(服务器 → 客户端) | 双向 | 双向 | 无保证 |
消息可靠性 | 高 | 高 | 高 | 不保证到达 |
小程序兼容性 | 极佳 | 好 | 插件限制 | 插件限制 |
资源消耗 | 极低 | 中等 | 较高 | 极低 |
适合场景 | 轻量推送 | 聊天、游戏 | 直播、音视频 | 本地组网 |
✅ 加入重连间隔限制(如 5秒后再连)
✅ 超过最大重试次数时提示用户
✅ 在 onShow
页面生命周期重新 connect
✅ 小程序后台挂起时停止轮询,降低资源消耗
✅ 服务器端推送规范化,每条消息完整 `
结束 ✅ 客户端按
` 分段处理
微信小程序虽然原生提供了 WebSocket,但在很多中小体量、轻量实时推送场景下,
采用基于 wx.request
+ enableChunked
+ onChunkReceived
自行实现的 SSE 客户端,
是一种极为合理且高效的实时通讯方案。
这种方案不仅兼容性好、开发简单,还能极大地降低服务器与客户端的复杂度。
在未来如果业务体量增长,也可以平滑升级为 WebSocket,不影响前期投入。
✅ 简单、轻量、优雅,是这套方案最大的优势!
推荐实践:小程序轻量推送优先考虑 SSE,自由双向通讯则采用 WebSocket!