vue3中使用sse最佳實(shí)踐,封裝工具詳解
vue3使用sse最佳實(shí)踐,封裝工具
工具
// 接受參數(shù)
export interface SSEChatParams {
url: string,// sse 連接
onmessage: (event: MessageEvent) => void,// 處理消息的函數(shù)
onopen: () => void,// 建立連接觸發(fā)的事件
finallyHandler: () => void,// 相當(dāng)于 try_finally 中的 finally 部分,不管出現(xiàn)異?;蛘哧P(guān)閉必然會(huì)執(zhí)行的代碼塊
}
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 連接已關(guān)閉");
} else {
console.error("SSE 錯(cuò)誤:", error);
}
sseChatParams.finallyHandler();
};
}
// 關(guān)閉連接
disconnect() {
if (this.eventSource) {
this.eventSource.close();
console.log("關(guān)閉 sse 連接")
if (this.finallyHandler != null) {
this.finallyHandler();
}
}
}
}
export const sseService = new SSEService();
使用
我在我代碼中是這樣使用的,就這么簡(jiǎn)單
const onopen = () => {
console.log("建立無(wú)敵 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
// 更新聊天數(shù)據(jù)源中的對(duì)話
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)
另外你可能還需要增加一下關(guān)閉觸發(fā)時(shí)機(jī)
// 當(dāng)組件從 DOM 中卸載前執(zhí)行的操作
onUnmounted(() => {
sseService.disconnect()
})這里需要提一嘴,關(guān)于 sse 中的 onopen 觸發(fā)時(shí)機(jī)
當(dāng)你和服務(wù)器建立 sse 連接的時(shí)候,如果后端沒(méi)有通過(guò) sse 返回給你消息的話,那么前端瀏覽器大概率是不會(huì)觸發(fā) onopen 事件。
所以當(dāng)與后端建立連接后要注意咯~
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
vue動(dòng)態(tài)路由實(shí)現(xiàn)多級(jí)嵌套面包屑的思路與方法
在實(shí)際項(xiàng)目中我們會(huì)碰到多層嵌套的組件組合而成,比如我們常見的面包屑導(dǎo)航,下面這篇文章就來(lái)給大家介紹關(guān)于vue實(shí)現(xiàn)動(dòng)態(tài)路由多級(jí)嵌套面包屑的思路與方法,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來(lái)一起看看吧。2017-08-08
簡(jiǎn)單說(shuō)說(shuō)如何使用vue-router插件的方法
這篇文章主要介紹了如何使用vue-router插件的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04
vue使用swiper實(shí)現(xiàn)中間大兩邊小的輪播圖效果
這篇文章主要介紹了vue使用swiper實(shí)現(xiàn)中間大兩邊小的輪播圖效果,本文分步驟通過(guò)實(shí)例代碼講解的非常詳細(xì),需要的朋友可以參考下2019-11-11
Vue3 的ref和reactive的用法和區(qū)別示例解析
ref和reactive是Vue3中用來(lái)實(shí)現(xiàn)數(shù)據(jù)響應(yīng)式的API,一般情況下,ref定義基本數(shù)據(jù)類型,reactive定義引用數(shù)據(jù)類型,本文給大家介紹Vue3 的ref和reactive的用法和區(qū)別,感興趣的朋友一起看看吧2023-10-10
vue+elementUI 實(shí)現(xiàn)內(nèi)容區(qū)域高度自適應(yīng)的示例
這篇文章主要介紹了vue+elementUI 實(shí)現(xiàn)內(nèi)容區(qū)域高度自適應(yīng)的示例,幫助大家更好的理解和使用vue,感興趣的朋友可以了解下2020-09-09
vue 解決數(shù)組賦值無(wú)法渲染在頁(yè)面的問(wèn)題
今天小編就為大家分享一篇vue 解決數(shù)組賦值無(wú)法渲染在頁(yè)面的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-10-10

