实战指南:利用`@microsoft/fetch-event-source`构建高效SSE流式聊天应用

1. 为什么SSE是流式聊天的“理想搭档”?

如果你最近在捣鼓AI聊天应用,尤其是想实现那种像真人打字一样、一个字一个字往外蹦的效果,那你肯定绕不开“流式输出”这个概念。传统的API请求是“一问一答”,你发个问题过去,后端吭哧吭哧算半天,最后把一整段完整的答案打包扔回来。用户只能盯着空白页面干等,体验非常割裂。而流式输出就像拧开了水龙头,数据是“涓涓细流”,持续不断地从服务器流向客户端,用户可以立刻看到生成过程,体验瞬间就流畅、自然了。

要实现这种效果,技术上主要有两大流派:WebSocketServer-Sent Events (SSE)。很多新手会纠结选哪个,我刚开始也一样。简单来说,WebSocket是双向通信的“高速公路”,功能强大,适合在线游戏、实时协作这种需要频繁双向交互的场景。但它的“收费站”(服务器连接开销)和“施工复杂度”(协议升级、心跳维护、重连逻辑)也更高。

而SSE,更像是服务器到客户端的“单向广播”。它基于最普通的HTTP协议,服务器可以主动推送消息,客户端只管接收就行。对于GPT流式聊天这种典型的“你问我答,我一边想一边说”的场景,SSE简直是量身定做。它的优势太明显了:实现简单(就是个特殊的HTTP响应),天然支持自动重连(连接断了浏览器自己会尝试重连),开销极低。我实测过,在只需要服务器推送的场景下,用SSE比用WebSocket,服务端的连接资源占用能少一大截,前端代码也清爽得多。

那么,在前端怎么接住SSE这股“数据流”呢?你可能会想到用原生的 EventSource API。没错,它能用,但我踩过坑。EventSource 有个很大的限制:它只支持GET请求,而且请求头是固定的,你没法自定义 Authorization 这种携带令牌的Header。在现代前后端分离、需要鉴权的应用里,这基本就是个“废柴”。所以,我们需要一个更强大的工具,这就是今天的主角—— @microsoft/fetch-event-source 库。它用Fetch API重新实现了SSE客户端,完美解决了 EventSource 的所有短板,让你既能享受SSE的轻便,又能拥有Fetch的全部灵活性。

2. 手把手入门:从零开始使用 @microsoft/fetch-event-source

说干就干,我们先把这个库用起来。安装过程毫无波澜,和你用过的任何前端库一样:

npm install @microsoft/fetch-event-source
# 或者
yarn add @microsoft/fetch-event-source
# 或者
pnpm add @microsoft/fetch-event-source

安装好后,我们来写一个最基础的请求。假设你的后端提供了一个SSE流式接口 /api/chat/stream。下面这段代码展示了如何发起请求并接收数据:

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

async function startStreamingChat(query) {
  // 定义一个控制器,用于在需要时主动中断流
  const controller = new AbortController();

  await fetchEventSource('/api/chat/stream', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      // 看这里!可以轻松添加认证头,这是原生EventSource做不到的
      'Authorization': `Bearer ${yourAuthToken}`,
    },
    body: JSON.stringify({
      message: query,
      // 你可以传递任何需要的参数
      temperature: 0.7,
      max_tokens: 1000,
    }),
    // 传入AbortSignal,用于控制请求中断
    signal: controller.signal,
    // 核心:当收到服务器发送的一个事件时触发
    onmessage(event) {
      // event.data 就是服务器推送过来的数据片段
      console.log('收到数据块:', event.data);
      // 通常,数据是JSON字符串,我们需要解析
      try {
        const parsedData = JSON.parse(event.data);
        // 假设后端返回 { content: “生成的文字”, done: false }
        if (parsedData.content) {
          // 更新UI,将内容追加到聊天窗口
          appendMessageToUI(parsedData.content);
        }
      } catch (e) {
        // 如果不是JSON,可能是纯文本或结束信号
        console.log('原始数据:', event.data);
      }
    },
    // 连接成功打开时触发
    onopen(response) {
      console.log('连接已建立,状态码:', response.status);
      // 你可以在这里处理响应头等信息
    },
    // 连接被服务器关闭时触发
    onclose() {
      console.log('服务器关闭了连接');
      // 可以在这里做一些清理工作,或者提示用户连接结束
    },
    // 发生错误时触发(包括网络错误、解析错误等)
    onerror(err) {
      console.error('流式请求发生错误:', err);
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值