前端json截断本质是sse中tcp字节流与data:消息边界不一致,需用uint8array缓冲+textdecoder({stream:true})保utf-8完整性,按\n\n组装data块,try-catch解析并支持断点续拼与校验。

前端遇到 JSON 截断,本质不是“某一段 JSON 被截断”,而是:SSE 的网络传输层(TCP)与消息逻辑层(data: {...}\n\n)不一致,导致 UTF-8 字节流被硬性切开,解码后出现非法字符、不完整 JSON 字符串或半条 data: 行。这时候靠“重试”或“跳过”解决不了问题,必须在二进制缓冲 + 行级解析层面做容错。
用 Uint8Array 缓冲区保字节完整性
不能一收到 reader.read() 的 chunk 就立刻 TextDecoder.decode()——中文、emoji 等多字节字符一旦被截断,解码就会出错或丢字。必须先在二进制层累积:
- 声明一个空的
Uint8Array作为缓冲区,每次读取后用set()合并新数据 - 使用
new TextDecoder('utf-8', { stream: true })解码,它能正确处理未结束的多字节序列,不会报错也不会丢字 - 只对解码后的字符串按
\n切行,但不急于解析;每行只保留为待处理文本,不立即JSON.parse()
按 SSE 消息边界(\n\n)组装完整 data 块
SSE 的语义单位是“一条消息”,以两个换行符 \n\n 结尾,不是单个 \n。一行 data: { 加下一行 "msg": "你好" 再加一行空行,才构成一条合法消息。所以:
- 把所有以
data:开头的连续非空行拼起来(去掉data:前缀),直到遇到空行为止 - 拼接结果就是完整的 payload 字符串,例如:
{"content":"Hello","index":0} - 如果拼到一半连接断了,缓冲区里残留的半条
data:行会留在Uint8Array中,下次续上继续拼——天然支持断点续拼
JSON 解析失败时降级处理,不中断流
即使消息完整,也可能因后端 bug 或字段缺失导致 JSON.parse() 报错。此时不能 throw 或停止 read 循环:
- 对每条拼好的 payload 字符串都用
try...catch包裹解析逻辑 - 解析失败时,记录错误日志(含原始字符串前 50 字),然后
continue处理下一行 - 可选增强:对常见截断模式做预判,比如字符串以
{"开头却没闭合,或末尾是,"、:"等,直接跳过该块
配合服务端加简单校验字段提升鲁棒性
纯靠前端容错有极限。建议后端在每条 data: 中加入轻量校验字段,例如:
-
seq递增序号,前端可检测是否跳号(说明中间有丢失) -
checksum可为内容前 16 字符的简单哈希,用于快速识别明显损坏 - 前端缓存最近 3 条成功解析的消息,若连续 2 条解析失败且
seq未推进,主动触发重连
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











