uni-app中不能直接用原生EventSource实现跨端SSE,需分平台处理:H5支持EventSource但需防CORS和gzip;微信小程序可用uni.request+onChunkReceived(需text/event-stream头且禁用gzip);App端不触发onChunkReceived,必须用plus.net.HttpRequest或WebSocket降级模拟。

uni-app 里不能直接用原生 EventSource 实现跨端 SSE,因为 App 端(iOS/Android)和微信小程序都不支持它;H5 端虽支持,但真机调试或上线后仍可能因 CORS、header 限制或缓存策略失败。必须分平台处理,且核心是「绕过 EventSource,手动解析流式响应」。
uni.request 能否用于接收 SSE 流式数据?
能,但有硬限制:uni.request 的 onHeadersReceived 和 onChunkReceived 回调仅在 H5 和微信小程序中可用(App 端不触发),且微信小程序要求服务端返回 Content-Type: text/event-stream 并禁用 gzip(Content-Encoding: identity)。否则会整包等待响应结束才触发 success,彻底失去流式意义。
- 必须显式设置
header.Accept = 'text/event-stream' - 微信小程序需在
manifest.json中开启"mp-weixin" → "webview" → "enablePullDownRefresh": false(避免下拉刷新中断连接) - App 端必须换方案——用
plus.net.HttpRequest(5+ SDK)或封装 WebSocket 模拟 SSE 协议 - 服务端响应头必须包含
Cache-Control: no-cache、Connection: keep-alive,否则 iOS WKWebView 会缓冲前几个 chunk
如何手动解析 text/event-stream 分块数据?
流式数据不是完整 JSON,而是以 data: {...}\n\n 或 event: message\nid: 1\ndata: ...\n\n 格式分段发送。关键难点是 ArrayBuffer 不按消息边界切分,一次 onChunkReceived 可能含半个消息、多个消息,或跨 chunk 拆开一个 data: 行。
- 维护全局
buffer字符串,每次追加safeDecodeUTF8(chunk)解码结果 - 用
buffer.split('\n\n')切分完整事件块,但要判断末尾是否截断(!buffer.endsWith('\n\n')) - 只取含
data:的块,用.replace(/^data:\s*/, '')剥离前缀再JSON.parse() - 别信
event:类型字段——多数大模型接口只发data:,忽略event:和id:
示例解码逻辑:
let buffer = '';
function decode(data) {
const text = safeDecodeUTF8(data);
buffer += text;
const chunks = buffer.split('\n\n').filter(c => c.trim());
if (!buffer.endsWith('\n\n') && chunks.length > 0) {
buffer = chunks.pop() || '';
} else {
buffer = '';
}
return chunks
.filter(c => c.includes('data:'))
.map(c => JSON.parse(c.replace(/^data:\s*/, '')));
}
App 端和小程序端的兼容性差异在哪?
微信小程序允许 uni.request 流式回调,但 App 端(iOS/Android)完全不触发 onChunkReceived。这是 uni-app 底层 WebView 实现差异导致的,无法通过配置修复。
- App 端唯一可靠路径:用
plus.net.HttpRequest(需启用 5+ SDK)并监听ondata事件,它原生支持 chunk 推送 - 若不用 5+ SDK,只能退化为短轮询(如每 200ms
uni.request一次带 last_id 参数),牺牲实时性保可用性 - 微信小程序真机测试时,务必关闭「调试基础库版本」的「最新稳定版」开关——某些基础库版本会静默丢弃非 200 响应的流数据
- H5 端最省事,但要注意 nginx 默认开启 gzip,必须加
gzip off;或服务端设置Vary: Accept-Encoding防止压缩破坏 event-stream 格式
真正麻烦的从来不是协议本身,而是 uni-app 把不同平台的底层网络栈抽象成同一套 API 后,反而掩盖了 onChunkReceived 这种关键回调的平台级缺失。写一套代码跑三端?先确认你愿意为 App 端多维护一套 plus.net 逻辑,还是接受流式体验在 App 上降级。


















