本文系統梳理了在微信小程序開發中,如何使用 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)**成為一個非常優秀的輕量級替代方案。
一、微信小程序常見通訊方式概覽
通訊方式 | 特點 | 適用場景 |
---|---|---|
HTTP Request | 無狀態、短連接 | 普通數據交互 |
WebSocket | 長連接、雙向通信 | 聊天、實時協作、游戲 |
TCP Socket | 底層高性能 | 小程序插件環境、直播等 |
UDP | 無連接、快速 | 一般用于局域網插件,不常用于小程序主流業務 |
SSE | 單向推送、長連接、輕量實現 | 輕量級推送、低頻實時更新 |
? 小程序原生支持 WebSocket,但 WebSocket 需要更高的資源管理。
? TCP/UDP 通常需要小程序插件權限,不適合普通業務。
二、什么是 SSE(Server-Sent Events)?
SSE(服務器發送事件) 是一種基于 HTTP 協議的推送機制,特點是:
- 單向通信:服務器主動向客戶端推送數據
- 復用 HTTP 連接:不需要建立新的專用連接
- 輕量、低開銷:比 WebSocket 簡單很多
- 天生兼容 HTTP 基礎設施
典型數據格式:
event: message
data: {"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 的對比分析
特性 | SSE | WebSocket | TCP | UDP |
---|---|---|---|---|
連接方式 | HTTP長連接 | 專用協議 | 低層連接 | 無連接 |
通訊方向 | 單向(服務器 → 客戶端) | 雙向 | 雙向 | 無保證 |
消息可靠性 | 高 | 高 | 高 | 不保證到達 |
小程序兼容性 | 極佳 | 好 | 插件限制 | 插件限制 |
資源消耗 | 極低 | 中等 | 較高 | 極低 |
適合場景 | 輕量推送 | 聊天、游戲 | 直播、音視頻 | 本地組網 |
七、常見問題與優化策略
1. 短時間內多次重連?
? 加入重連間隔限制(如 5秒后再連)
? 超過最大重試次數時提示用戶
2. 后臺掛起導致連接斷開?
? 在 onShow
頁面生命周期重新 connect
? 小程序后臺掛起時停止輪詢,降低資源消耗
3. 數據粘包、拆包問題?
? 服務器端推送規范化,每條消息完整 `
結束 ? 客戶端按
` 分段處理
八、總結
微信小程序雖然原生提供了 WebSocket,但在很多中小體量、輕量實時推送場景下,
采用基于 wx.request
+ enableChunked
+ onChunkReceived
自行實現的 SSE 客戶端,
是一種極為合理且高效的實時通訊方案。
這種方案不僅兼容性好、開發簡單,還能極大地降低服務器與客戶端的復雜度。
在未來如果業務體量增長,也可以平滑升級為 WebSocket,不影響前期投入。
? 簡單、輕量、優雅,是這套方案最大的優勢!
推薦實踐:小程序輕量推送優先考慮 SSE,自由雙向通訊則采用 WebSocket!