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