Vue3+ts sse封装

什么是 sse

SSE(Server-Sent Events)是一种基于 HTTP 协议,用于实现服务器主动向客户端推送数据的技术。它在客户端与服务器之间建立一条持久化连接,并通过这条连接实现服务器向客户端的实时数据推送,而客户端不能发送数据给服务端。

SSE是一种允许服务器向客户端单向发送数据的技术

和 websocket 不同 ,websocket 是客户端和服务器可以双向发送数据,sse 技术常用与 消息推送,websocket 常用与 聊天

为什么选择 sse

我最近写的是模仿 ai 的一个流式输出,前端需要做的就只是接收 后端所传递过来的若干数据,并且实现流式输出,重点是 : 我们只用接收,而不必去向服务器发送数据

使用 sse

sse 和 websocket 的方法差不多 提供的也是几个回调函数 onopen、onmessage、onerror 、onclose

vue3+ts 建立sse连接代码

ini 复制代码
const eventSource = ref<EventSource | null>();

const initSSE = () => {
  eventSource.value = new EventSource("http://地址");

  eventSource.value.onmessage = (event) => {
    console.log("收到消息内容是:", event.data);
  };

  eventSource.value.onerror = (error) => {
    console.error("SSE 连接出错:", error);
    eventSource.value!.close();
  };
};

onMounted(() => {
  initSSE();
});

onUnmounted(() => {
  if (eventSource) {
    eventSource.value?.close();
  }
});

然后 在实际运用过程中,我发现如上代码是get请求,实际开发中是 post 请求。sse 本身不支持 post 请求

于是我们需要借助 fetchEventSource 来实现 sse 的 post 请求

使用 fetchEventSource 建立 sse 的 post 请求

安装

css 复制代码
pnpm i @microsoft/fetch-event-source

使用

javascript 复制代码
await fetchEventSource(
    getForumAIUrl("你的地址",
    {
      method: "POST",
      headers: {
        "Content-Type": "application/json;charset=utf-8",
      },
      body: JSON.stringify({
        //你的数据,也可以不传
      }),
      openWhenHidden: true,
      onopen() {},
      onmessage(event) {
        isLoading.value = false;

        let data = JSON.parse(event.data);
        //处理业务逻辑
      },
      onerror(error) {
        console.error("SSE 连接出错:", error);
      },
    }
  );

以上就是建立了一个 sse 的 post 连接

但是我在写代码的过程中 ,又发现很多地方都需要用到这个 sse 技术,能不能给他封装起来,以便于我们更好的使用,于是我便开始了封装之路

封装 sse

思路: 考虑到 我们其实只需要传递 需要的url,方法,以及数据,有时候需要 在header 中设置 一些 key 来访问,并且我们大部分业务逻辑只关心 onmessage 事件的触发 和使用

在 utils 目录下 新建了 一个 sse.ts 文件

以下是所有的代码

typescript 复制代码
import { fetchEventSource } from "@microsoft/fetch-event-source";
import { ElMessage } from "element-plus";

// 定义消息回调类型
type MessageHandler = (data: any) => void;

export class SSEService {
  async connect(
    url: string,
    method: "GET" | "POST",
    body: object,
    onMessageHandler: MessageHandler,
    myHeader?: Record<string, string> // 键值对的形式
  ) {
    return await fetchEventSource(url, {
      method: method,
      headers: {
        "Content-Type": "application/json;charset=utf-8",
        ...myHeader, // 当 myHeader 未定义时会自动忽略展开
      },
      body: JSON.stringify(body),
      openWhenHidden: true,
      async onopen() {
        // 可以在这里添加连接成功逻辑
      },
      onmessage(event) {
        onMessageHandler(event);
      },
      onerror(error) {
        ElMessage.error("SSE连接出错: " + error);
      },
      onclose(){

      }
    });
  }
}

通过封装成 SSEService 类,并且在触发 onmessage 事件时,调用 我们传递进去的 函数,这样我们就可以使用,并且支持 headers 添加自己想要的内容

使用示例代码

ini 复制代码
 import { SSEService } from "@/utils/sse";

 let sse = new SSEService();

 sse.connect(
    getForumAIUrl(currentConversition.value!.id) +
      `?search_enabled=${isInternet.value}`,
    "POST",
    {
      query: sendText.value,
      stream: true,
      history: [],
    },
    (event: any) => {
      // 这里处理收到的消息
      let data = JSON.parse(event.data);
      console.log("收到SSE消息:", data);
      //下面的业务逻辑可以替换成你自己的
      isLoading.value = false;
      if (data?.done) {
        return;
      }

      if (data?.content) {
        let decodeContent = decodeUnicode(data!.content);
        console.log(decodeContent);

        handleRender(decodeContent);
      } else {
        setTimeout(() => {
          isLoading.value = false;
        });
      }
    }
  );

然后这就封装好并且使用了,不用每次都写 冗余的代码去建立 sse 连接了

相关推荐
若云止水6 小时前
ngx_conf_handler - root html
服务器·前端·算法
佚明zj6 小时前
【C++】内存模型分析
开发语言·前端·javascript
知否技术7 小时前
ES6 都用 3 年了,2024 新特性你敢不看?
前端·javascript
最初@8 小时前
el-table + el-pagination 前端实现分页操作
前端·javascript·vue.js·ajax·html
知否技术9 小时前
JavaScript中的闭包真的过时了?其实Vue和React中都有用到!
前端·javascript
Bruce_Liuxiaowei9 小时前
基于Flask的防火墙知识库Web应用技术解析
前端·python·flask
zhu_zhu_xia9 小时前
vue3中ref和reactive的差异分析
前端·javascript·vue.js
拉不动的猪9 小时前
刷刷题45 (白嫖xxx面试题1)
前端·javascript·面试
幼儿园技术家9 小时前
使用SPA单页面跟MPA多页面的优缺点?
前端
还是鼠鼠9 小时前
认识 Express.js:Node.js 最流行的 Web 框架
开发语言·前端·javascript·vscode·node.js·json·express