NDJSON、SSE 与流式协议边界

对比 NDJSON 与 SSE 的记录边界、元数据、客户端能力和代理行为,并说明流读取与事件解析的分层。

#type / synthesis #status / evergreen #tech / dev / frontend #resource / javascript #protocol / http

[!info] related notes

NDJSON、SSE 与流式协议边界

共同目标

NDJSON 和 SSE 都允许服务端在一个 HTTP 响应中逐条发送记录,但它们定义记录边界的方式不同。

维度NDJSONSSE
常见媒体类型application/x-ndjsontext/event-stream
记录单位每行一个 JSON 值空行分隔事件,内部有 event:data: 等字段
元数据放进 JSON 对象协议自带 event/id/retry 字段
原生浏览器 API通常用 fetch + Streams可用 EventSource,也可用 fetch
请求方式fetch 可使用任意方法和请求体EventSource 主要面向 GET

正确的解析分层

HTTP body 字节块
  -> TextDecoder 还原字符
  -> 协议解析器识别完整行/事件
  -> JSON.parse 得到 unknown
  -> 运行时契约校验
  -> 业务事件 reducer

每层只解决一种边界。JSON.parse 不应该直接处理任意网络块,业务 reducer 也不应该负责拼接半行。

SSE 要点

  • 一个事件可包含多个 data: 行。
  • 空行表示事件结束。
  • : 开头是注释,可用于 keep-alive。
  • id: 可帮助断线恢复,但客户端和服务端必须共同定义回放策略。

NDJSON 要点

  • 每一行必须是独立合法 JSON。
  • JSON 字符串内部的换行应被转义,不能成为实际记录分隔符。
  • 最后一行是否必须以换行结尾需要在协议中明确。

工程选择

  • 需要 POST 请求体、结构简单、双端都自己控制:NDJSON 很直接。
  • 需要浏览器原生重连语义或标准事件字段:SSE 更合适。
  • 无论选择哪种,都要处理代理缓冲、心跳、取消、错误事件和断线后的重复/缺失。
创建于 2026/7/29 更新于 2026/7/29