在 AI 大模型(如 ChatGPT)时代,流式数据传输(Streaming)变得越来越普遍。

而在前端实现 SSE 实时接收服务器推送数据,主要有以下三种方式。本文将按照推荐程度从高到低进行排列。
前端实现 SSE(Server-Sent Events)的三种方式

📊 三种SSE实现方式对比概览

前端SSE实现方式

🥇 终极推荐
@microsoft/fetch-event-source

🥈 次推荐
原生fetch + ReadableStream

🥉 特定场景
原生EventSource API

✅ 支持POST请求

✅ 自定义Headers

✅ 自动重连

✅ 完善异常处理

✅ 支持POST请求

✅ 自定义Headers

❌ 手动解析SSE

❌ 手动重连

❌ 仅GET请求

❌ 无法自定义Headers

✅ 原生自动重连

✅ 浏览器原生支持

推荐场景:AI聊天、复杂业务

推荐场景:轻量级、无依赖

推荐场景:单向通知、监控看板

一、 🥇 终极推荐:使用 @microsoft/fetch-event-source

这是目前在 AI 聊天等复杂业务场景中最推荐、最主流的实现方式。它由微软官方开源,本质上是基于原生的 fetch 进行了封装。

为什么最推荐?

  • 支持 POST 请求: 原生 API 只支持 GET,而 AI 场景通常需要传复杂的 JSON(如 Prompt 历史记录、模型参数),用 POST 极为方便。
  • 支持自定义 Headers: 可以像普通 fetch 一样直接在请求头里携带 Authorization Token,完美解决鉴权痛点。
  • 内置自动重连: 继承了 SSE 的优良传统,网络断开时会自动重连。
  • 异常处理更完善: 允许你捕获 HTTP 状态码错误(如 401、500)并决定是否停止连接。

🛠️ 核心实现代码

首先需要安装依赖:

npm install @microsoft/fetch-event-source

前端调用代码:

import { fetchEventSource } from '@microsoft/fetch-event-source';

async function startStream() {
    await fetchEventSource('/api/chat', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'Authorization': 'Bearer YOUR_TOKEN' // 完美支持 Token 鉴权
        },
        body: JSON.stringify({
            model: "gpt-4",
            messages: [{ role: "user", content: "你好!" }]
        }),
        onmessage(msg) {
            // 库会自动解析好 SSE 格式,直接通过 msg.data 拿到文本
            if (msg.data === '[DONE]') {
                console.log('数据流传输结束');
                return;
            }
            console.log('收到数据:', msg.data);
            // 在此处更新你的 UI 视图
        },
        onclose() {
            console.log('连接正常关闭');
        },
        onerror(err) {
            console.error('发生错误:', err);
            // 可以在这里 return 阻止它自动重连
        }
    });
}

二、 🥈 次推荐:使用原生 fetch + ReadableStream 纯手动解析

如果你不想引入第三方依赖,或者项目环境受限,可以使用现代浏览器自带的 fetch API 来手动读取底层的二进制数据流。

优缺点分析

  • 优点: 摆脱了原生 EventSource 的限制,支持 POST 请求,支持自定义 Headers,不需要安装任何 npm 包。

  • 缺点: 需要自己使用 TextDecoder 解码二进制流,并且需要自己写循环去解析 data: … 文本,还要处理长文本被截断、切碎成多个 Chunk 时的粘包/碎包问题。此外,断线重连需要自己写代码实现。

🛠️ 核心实现代码

async function startFetchStream() {
    const response = await fetch('/api/chat', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'Authorization': 'Bearer YOUR_TOKEN'
        },
        body: JSON.stringify({ prompt: '你好' })
    });

    // 1. 获取响应体的读取器 (Reader)
    const reader = response.body.getReader();
    const decoder = new TextDecoder('utf-8'); 

    // 2. 开启循环,不断读取流数据
    while (true) {
        const { done, value } = await reader.read();
        if (done) {
            break;
        }

        // 3. 将 Uint8Array 转换为文本
        const chunkText = decoder.decode(value);
        
        // 4. 手动解析 SSE 的字符串格式
        const lines = chunkText.split('\n');
        for (const line of lines) {
            if (line.startsWith('data:')) {
                const dataContent = line.replace('data:', '').trim();
                console.log('收到解析后的数据:', dataContent);
            }
        }
    }
}

三、 🥉 仅特定场景推荐:使用浏览器原生 EventSource API

这是 HTML5 标准中自带的 API。如果你的业务非常简单,不需要复杂的鉴权,也不需要发 POST 请求,可以使用它。

为什么不推荐作为首选?

  • 致命痛点 1:只支持 GET 请求。 无法发送复杂的 Body 体。

  • 致命痛点 2:无法自定义请求头(Headers)。 这意味着你不能在 Header 里加 Authorization,只能通过 URL 传参(如 /sse?token=xxx)将 Token 暴露在外,存在安全隐患。

它的闪光点:

  • 浏览器原生自带,不需要任何包装。

  • 内置极其强悍的自动重连机制,断线后不仅能自动重连,还会自动通过 Last-Event-ID 请求头告诉后端它上次听到哪了,方便后端补发消息。

🛠️ 核心实现代码

function startNativeSSE() {
    // 只能发送 GET 请求,Token 只能憋屈地挂在 URL 上
    const eventSource = new EventSource('/api/sse/stream?token=YOUR_TOKEN');

    // 监听默认的 message 事件
    eventSource.onmessage = function(event) {
        console.log("收到新数据:", event.data);
    };

    // 监听连接建立
    eventSource.onopen = function() {
        console.log("SSE 长连接建立成功");
    };

    // 监听错误
    eventSource.onerror = function(error) {
        console.error("连接出错或断开", er    // 如果中途想主动关闭:
    // eventSource.close();
    }
}

## 🔄 三种方案数据流对比## 🔄 三种方案数据流对比
## 💡 总结与选型指南

 1. AI 聊天、需要 Token 认证、需要传复杂参数: 毫不犹豫选择 @microsoft/fetch-event-source。

2. 轻量级、无需依赖、不怕麻烦想硬核手撕: 选择 原生 fetch + 可读流 方案。

3. 传统单向大屏通知、后台监控看板、不需要复杂鉴权: 选择 原生 EventSource。
Logo

免费领 150 小时云算力,进群参与显卡、AI PC 幸运抽奖

更多推荐