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 事件。
所以当与后端建立连接后要注意咯~
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论