vue3 中使用 sse 最佳实践,封装工具

在这里插入图片描述

工具

// 接受参数
export interface SSEChatParams {
   
    url: string,// sse 连接
    onmessage: (event: MessageEvent) => void,// 处理消息的函数
    onopen: () => void,// 建立连接触发的事件
    finallyHandler: () => void,// 相当于 try_finally 中的 finally 部分,不管出现异常或者关闭必然会执行的代码块
}


class SSEService {
   
    private eventSource: EventSource | null = null;

    private finallyHandler: (() => void) | undefined;

    // 建立连接
    connect(sseChatParams: SSEChatParams) {
   

        this.finallyHandler = sseChatParams.finallyHandler;

        this.eventSource = new EventSource(sseChatParams.url);

        if (sseChatParams.onopen != null) {
   
            this.eventSource.onopen = sseChatParams.onopen;
        }else{
   
            this.eventSource.onopen = () => {
   
                console.log('SSE 连接已开启');
            };
        }

        if (sseChatParams.onmessage != null) {
   
            this.eventSource.onmessage = sseChatParams.onmessage;
        } else {
   
            this.eventSource.onmessage = (event) => {
   
                console.log('收到消息:', event.data);
            };
        }

        this.eventSource.onerror = (error) => {
   
            if (this.eventSource?.readyState === EventSource.CLOSED) {
   
                console.log("SSE 连接已关闭");
            } else {
   
                console.error("SSE 错误:", error);
            }
            sseChatParams.finallyHandler();
        };
    }

    // 关闭连接
    disconnect() {
   
        if (this.eventSource) {
   
            this.eventSource.close();
            console.log("关闭 sse 连接")
            if (this.finallyHandler != null) {
   
                this.finallyHandler();
            }
        }
    }
}

export const sseService = new SSEService();

使用

我在我代码中是这样使用的,就这么简单

const onopen = () => {
   
  console.log("建立无敌 sse 连接成功")
}
// 建立连接
let sseChatParams: SSEChatParams = {
   
  onopen,
  url: import.meta.env.VITE_GLOB_API_URL + 'sse/createConnect?clientId=' + userStore.getSseClientId(),
  onmessage: (event: MessageEvent) => {
   
    // 收到消息
    console.log('收到消息xsssx:', event.data);
    let chunk = event.data;
    if (chunk === '[DONE]') {
   
      sseService.disconnect()
      state.imageList = []
      chatGuide(chatStore.activeChatId).then(resp => {
   
        chatGuideList.value = resp.data.guideList
        scrollViewBottom()
      })
      return
    }
    chunk = JSON.parse(chunk)
    if (chunk.type === 'error') {
   
      errorText = chunk.content
      console.log("errorText", errorText);
      updateChatData(errorText)
      return;
    }
    chunk = chunk.content;
    if (!chunk) {
   
      return;
    }
    lastText = lastText + chunk
    // 更新聊天数据源中的对话
    updateChatData(lastText)
  },
  finallyHandler: () => {
   
    console.log("finallyHandler操作")
    sessionStatus.value = 0
    inputDisabled.value = false
    dataSources.value[dataSources.value.length - 1].loading = false
    loading.value = false
    if (!isMobile.value) {
   
      // 聚焦输入框
      inputRef.value?.focus()
    }
  }
};
sseService.connect(sseChatParams)

另外你可能还需要增加一下关闭触发时机

// 当组件从 DOM 中卸载前执行的操作
onUnmounted(() => {
   
    sseService.disconnect()
})

这里需要提一嘴,关于 sse 中的 onopen 触发时机

当你和服务器建立 sse 连接的时候,如果后端没有通过 sse 返回给你消息的话,那么前端浏览器大概率是不会触发 onopen 事件。

所以当与后端建立连接后要注意咯~


最后介绍一下自己的网站术士 AI:术士AI 2.0 (shushiai.com)

有兴趣用用玩玩,最好也支持一下,谢谢

相关推荐

  1. vue3常用组件封装使用

    2023-12-05 23:04:05       24 阅读
  2. vue3实现地区下拉选择组件封装

    2023-12-05 23:04:05       29 阅读
  3. Vue.js 3 封装全屏功能工具

    2023-12-05 23:04:05       44 阅读
  4. vue3封装table表格

    2023-12-05 23:04:05       33 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2023-12-05 23:04:05       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2023-12-05 23:04:05       106 阅读
  3. 在Django里面运行非项目文件

    2023-12-05 23:04:05       87 阅读
  4. Python语言-面向对象

    2023-12-05 23:04:05       96 阅读

热门阅读

  1. 前端请求patch接口,只传入已修改字段值的字段

    2023-12-05 23:04:05       50 阅读
  2. PHP 判断给定两个时间是否在同一周,月,年

    2023-12-05 23:04:05       67 阅读
  3. 【Android】WebView 基本使用

    2023-12-05 23:04:05       46 阅读
  4. 自定义中间件

    2023-12-05 23:04:05       48 阅读
  5. 解读DreamPose:基于Diffusion Models的模特视频生成

    2023-12-05 23:04:05       66 阅读
  6. 传统算法:使用Pygame实现SVM(支持向量机)算法

    2023-12-05 23:04:05       62 阅读
  7. C++11的互斥量

    2023-12-05 23:04:05       57 阅读