前端流式通信完整指南
🎯 SSE + Fetch Streaming + WebSocket 三种方案对比,LLM 打字机效果实战
📚 内容导航
SSE (Server-Sent Events)
- 协议原理与核心认知
- EventSource API 使用
- 服务端实现
- React 集成
Fetch Streaming
- POST SSE 方案
- ReadableStream 数据流转
- 格式解析与处理
生态工具与库
- fetch-event-source
- Vercel AI SDK
- OpenAI SDK
- eventsource-parser
AbortController 取消请求
- 基础用法
- 完整 ChatStream 类
- 超时控制
服务端实现
- Node.js 实现
- Edge Function
- 通用推流函数
React 集成
- useChatStream Hook
- ChatUI 组件
- 打字机光标动画
高级用法与面试题
- TransformStream 管道
- 流中断恢复
- 面试高频问题
1. 流式通信架构总览
1.1 三种方案对比
┌─────────────────────────────────────────────────────────────────────────┐
│ 前端流式通信方案对比 │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ 特性 │ SSE (EventSource) │ Fetch Streaming │ WebSocket │
│ ────────────────┼───────────────────┼─────────────────┼───────────── │
│ 方向 │ 服务端→客户端 │ 服务端→客户端 │ 双向 │
│ 请求方法 │ 仅 GET │ 任意 (POST) │ 独立协议 │
│ 自定义 Header │ ❌ │ ✅ │ ❌ │
│ 取消请求 │ close() │ AbortController │ close() │
│ 自动重连 │ ✅ 内置 │ ❌ 需手动 │ ❌ 需手动 │
│ 二进制数据 │ ❌ │ ✅ │ ✅ │
│ 浏览器支持 │ IE 不支持 │ 全面支持 │ 全面支持 │
│ 复杂度 │ 低 │ 中 │ 中 │
│ │
│ 推荐场景: │
│ • SSE: 简单通知推送、无需认证的公开流 │
│ • Fetch Streaming: LLM 对话 (需 POST + Authorization) │
│ • WebSocket: 实时双向通信 (聊天室、协作编辑) │
│ │
│ 生态库支持: │
│ • SSE: EventSource (原生) │
│ • Fetch Streaming: @microsoft/fetch-event-source、Vercel AI SDK │
│ • WebSocket: Socket.io、ws │
│ │
└─────────────────────────────────────────────────────────────────────────┘1.2 LLM 流式架构
┌─────────────────────────────────────────────────────────────────────────┐
│ LLM 流式响应完整架构 │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ POST /chat ┌──────────────┐ │
│ │ React UI │ ────────────────────▶ │ BFF/Edge │ │
│ │ │ Authorization: │ Function │ │
│ │ ┌────────┐ │ Bearer xxx └──────┬───────┘ │
│ │ │ChatBox │ │ │ │
│ │ └────────┘ │ │ stream: true │
│ │ │ │ ▼ │
│ │ │ │ ┌──────────────┐ │
│ │ ▼ │ ◀────────────────── │ OpenAI API │ │
│ │ ┌────────┐ │ SSE: data: {...} │ GPT-4 │ │
│ │ │Markdown│ │ data: {...} └──────────────┘ │
│ │ │Render │ │ data: [DONE] │
│ │ └────────┘ │ │
│ └──────────────┘ │
│ │
│ 数据流转: │
│ ───────── │
│ fetch(POST) → response.body (ReadableStream) │
│ → reader.read() (Uint8Array) │
│ → TextDecoder.decode() (string) │
│ → 解析 SSE "data: {...}" │
│ → JSON.parse() → delta.content │
│ → setState() → UI 更新 │
│ │
└─────────────────────────────────────────────────────────────────────────┘