Skip to content

前端流式通信完整指南

🎯 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 更新                                   │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

前端面试知识库