前端流式输出实现:基于 Fetch API 的 SSE 实践

发表于 2026-01-03 21:56 706 字 4 min read

暂无目录
深度解析什么是流式输出、为什么需要它,以及前端如何使用 Fetch API 配合 Streams API 实现健壮的 SSE 数据解析与业务逻辑分发。

写在前面: 流式输出就和它的名字一样,呈现一种水流形式一点一点进行输出。它是服务端对客户端的一种响应形式,这种输出使得响应数据可以一点点加载到页面上,避免用户等待很长时间,极大提高了用户体验。本文主要讲前端如何实现 SSE(Server-Sent Events)输出加载。

流式输出的概念

什么是流式输出?

流式输出就和它的名字一样,呈现一种水流形式一点一点进行输出。它是服务端对客户端的一种响应形式,这种输出使得响应数据可以一点点加载到页面上,避免用户等待很长时间,极大提高了用户体验。

图中所示就是一种典型的流式输出(用户和聊天机器人聊天的网络请求响应): SSE 是单向输出,仅支持服务器向客户端发送消息。但在 AI 时代,用户通常需要向服务端传输复杂的 Body 信息数据(如 Prompt、上下文历史等),因此大多数现代流式输出方案都是基于 POST 形式的 HTTP 请求实现的。

为什么要有流式输出?

  1. 即时反馈:早期的大语言模型生成内容时是逐个 Token 产生的,如果等待内容全部生成才显示,用户需要忍受漫长的空白等待。
  2. 降低感知延迟:流式输出可以解决这个问题,显著减少用户感知的延迟,极大提高了用户的响应感官速度。

流式输出的实现

核心实现方案:Fetch API

对于这种不寻常的输出,前端应该怎么做? SSE 有它自己独特的响应接收形式,我们需要使用最底层的请求方式来实现它。我们通过 Fetch API 来实现。

  • EventSource 的局限性:原生 EventSource 只支持 GET 请求,无法在 Body 中发送 JSON 数据,且不支持自定义 Headers(如 Authorization),这在现代鉴权系统中是致命的。
  • Fetch 的优势:Fetch 支持 POST,支持自定义 Headers,且通过 response.body.getReader() 可以实现与 SSE 完全一致的流式读取。

实现步骤详解

第一步: 建立连接 流式输出虽然是获取数据,但由于需要携带复杂的 Data,通常使用 POST 方法并配置相应的请求头。

第二步: 使用 Streams API 实现流式读取 传统的 API 是等待整个 Response 下载完成,但使用 Stream 可以实现:后端生成一个字,前端收到一个字。内存占用极低,且用户能立即看到反馈。

const reader = response.body.getReader();
const { done, value } = await reader.read();