// 接受参数 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 事件。
所以当与后端建立连接后要注意咯~
以上为个人经验,希望对您有所帮助。