Vue3實(shí)現(xiàn)SSE(Server-Sent?Events)連接
在現(xiàn)代 web 開發(fā)中,Server-Sent Events (SSE) 是一種輕量級的技術(shù),允許服務(wù)器通過 HTTP 持久連接向客戶端推送實(shí)時(shí)更新。在本文中,我們將探討如何在 Vue 3 應(yīng)用中實(shí)現(xiàn) SSE 連接,并處理接收到的消息。
什么是 SSE
SSE 是一種允許服務(wù)器向?yàn)g覽器推送事件的技術(shù)。與 WebSocket 不同,SSE 是單向的:服務(wù)器可以向客戶端發(fā)送數(shù)據(jù),而客戶端不能直接向服務(wù)器發(fā)送數(shù)據(jù)。SSE 適用于需要實(shí)時(shí)更新的應(yīng)用,比如聊天應(yīng)用、通知系統(tǒng)和實(shí)時(shí)數(shù)據(jù)監(jiān)控。
核心代碼示例
let retryCount = 0;
const maxRetries = 5; // 最大重試次數(shù)
const maxRetryDelay = 30000; // 最大重連時(shí)間,30秒
// 當(dāng)前用戶身份
const username = ref("");
// 初始化 SSE 連接
let eventSource: EventSource;
const initializeSSE = () => {
// 連接SSE
// 定義SSE鏈接參數(shù)
let url =
import.meta.env.VITE_BASE_API +
"/notification/socket_connection?username=" +
encodeURIComponent(username.value);
// 監(jiān)聽連接打開事件
eventSource = new EventSource(url);
eventSource.onopen = () => {
console.log("建立 SSE 連接成功");
};
// 監(jiān)聽消息事件
eventSource.onmessage = event => {
// 收到消息
chunk.value = JSON.parse(event.data);
console.log("收到的類型:", chunk.value.notice_type, 222);
// 根據(jù) notice_type 處理不同的通知類型
switch (chunk.value.notice_type) {
case 0:
userThumNotification();
break;
case 1:
userStarNotification();
break;
case 2:
userComNotification();
break;
case 3:
systemNotice();
break;
case 4:
managerNotice();
break;
case 5:
// 暫時(shí)擱置,用其他方法代替
if (storedRole.value !== "user") {
reportEmail();
}
break;
default:
console.warn("未知通知類型:", chunk.value.notice_type);
}
showNotify();
};
// 監(jiān)聽錯(cuò)誤事件
eventSource.onerror = () => {
console.error("SSE 連接發(fā)生錯(cuò)誤,嘗試重連...");
eventSource.close(); // 關(guān)閉當(dāng)前連接
handleReconnect(); // 嘗試重連
};
};
const handleReconnect = () => {
if (username.value !== "") {
console.log("連接已關(guān)閉, 嘗試重新連接");
if (retryCount < maxRetries) {
retryCount++;
const retryDelay = Math.min(
1000 * Math.pow(2, retryCount),
maxRetryDelay
); // 計(jì)算重連延遲
setTimeout(initializeSSE, retryDelay);
} else {
showToast("網(wǎng)絡(luò)連接不穩(wěn)定,請檢查網(wǎng)絡(luò)或重新登錄。");
console.log("已達(dá)到最大重試次數(shù),停止重連。");
}
}
};舉例:全局狀態(tài)管理消息總數(shù)
假設(shè)我們有三種通知類型:
點(diǎn)贊、評論、收藏
在userStore中進(jìn)行全局狀態(tài)管理,動態(tài)更新消息數(shù)量:
import { defineStore } from "pinia";
import { ref, computed } from "vue";
import { getManagerNotification } from "@/api/user";
import { getreportEmail } from "@/api/user";
import { getSystemNotification } from "@/api/user";
import {
getUserThumNotification,
getUserComNotification,
getUserStarNotification
} from "@/api/user";
import { showToast } from "vant";
// import { showNotify } from "vant";
//用戶信息管理
export const useInformation = defineStore(
"notication",
() => {
let retryCount = 0;
const maxRetries = 5; // 最大重試次數(shù)
const maxRetryDelay = 30000; // 最大重連時(shí)間,30秒
// 是否顯示SSE彈框
const noticeShow = ref(false);
// 接收到的SSE消息
const chunk = ref();
// 當(dāng)前用戶身份
const username = ref("");
const storedRole = ref("");
// 系統(tǒng)最新一條通知
const systemData = ref({});
// 管理員最新一條通知
const managerData = ref({});
// 用戶未讀消息
const thumb = ref(0);
const comment = ref(0);
const star = ref(0);
// 管理員未讀消息數(shù)
const manager_count = ref(0);
// 系統(tǒng)未讀消息數(shù)
const system_count = ref(0);
// 郵箱未讀消息數(shù)
const email_count = ref(0);
// 互動通知
// 默認(rèn)活躍的tab欄
const activeTab = ref(0);
// 總數(shù)
// 使用計(jì)算屬性動態(tài)獲取 total
const total = computed(() => {
return (
thumb.value +
comment.value +
star.value +
manager_count.value +
system_count.value
);
});
// 通用的獲取未讀通知數(shù)量的函數(shù)
const fetchNotificationCount = async (fetchFunction, refData, refCount) => {
try {
const res = await fetchFunction({ page: 1, limit: 1 });
if (refData != null) {
refData.value = res.data;
}
refCount.value = res.data.unread_count;
} catch (error) {
console.error("獲取通知時(shí)發(fā)生錯(cuò)誤:", error);
}
};
// 獲取系統(tǒng)消息
const systemNotice = () => {
fetchNotificationCount(getSystemNotification, systemData, system_count);
console.log(system_count.value);
};
// 獲取管理員消息
const managerNotice = () => {
fetchNotificationCount(
getManagerNotification,
managerData,
manager_count
);
};
// 獲取點(diǎn)贊通知的未讀消息數(shù)量
const userThumNotification = () => {
fetchNotificationCount(getUserThumNotification, null, thumb);
};
// 獲取評論通知的未讀消息數(shù)量
const userComNotification = () => {
fetchNotificationCount(getUserComNotification, null, comment);
};
// 獲取收藏通知的未讀消息數(shù)量
const userStarNotification = () => {
fetchNotificationCount(getUserStarNotification, null, star);
};
// 獲取舉報(bào)郵箱消息
const reportEmail = async () => {
fetchNotificationCount(getreportEmail, null, email_count);
};
// 獲取頁面消息
const userNotice = async () => {
await Promise.all([
userThumNotification(),
userComNotification(),
userStarNotification()
]);
};
// 初始化函數(shù)
const initNotifications = () => {
console.log(username, "哈哈哈紅紅火火恍恍惚惚");
systemNotice();
managerNotice();
userNotice();
if (storedRole.value !== "user") {
reportEmail();
}
// 打印 total,確保它是最新的
console.log("Total after initialization:", total.value);
};
const showNotify = () => {
noticeShow.value = true;
setTimeout(() => {
noticeShow.value = false;
}, 3000);
};
// 初始化 SSE 連接
let eventSource: EventSource;
const initializeSSE = () => {
// 連接SSE
// 定義SSE鏈接參數(shù)
let url =
import.meta.env.VITE_BASE_API +
"/notification/socket_connection?username=" +
encodeURIComponent(username.value);
// 監(jiān)聽連接打開事件
eventSource = new EventSource(url);
eventSource.onopen = () => {
console.log("建立 SSE 連接成功");
};
// 監(jiān)聽消息事件
eventSource.onmessage = event => {
// 收到消息
chunk.value = JSON.parse(event.data);
console.log("收到的類型:", chunk.value.notice_type, 222);
// 根據(jù) notice_type 處理不同的通知類型
switch (chunk.value.notice_type) {
case 0:
userThumNotification();
break;
case 1:
userStarNotification();
break;
case 2:
userComNotification();
break;
case 3:
systemNotice();
break;
case 4:
managerNotice();
break;
case 5:
// 暫時(shí)擱置,用其他方法代替
if (storedRole.value !== "user") {
reportEmail();
}
break;
default:
console.warn("未知通知類型:", chunk.value.notice_type);
}
showNotify();
};
// 監(jiān)聽錯(cuò)誤事件
eventSource.onerror = () => {
console.error("SSE 連接發(fā)生錯(cuò)誤,嘗試重連...");
eventSource.close(); // 關(guān)閉當(dāng)前連接
handleReconnect(); // 嘗試重連
};
};
const handleReconnect = () => {
if (username.value !== "") {
console.log("連接已關(guān)閉, 嘗試重新連接");
if (retryCount < maxRetries) {
retryCount++;
const retryDelay = Math.min(
1000 * Math.pow(2, retryCount),
maxRetryDelay
); // 計(jì)算重連延遲
setTimeout(initializeSSE, retryDelay);
} else {
showToast("網(wǎng)絡(luò)連接不穩(wěn)定,請檢查網(wǎng)絡(luò)或重新登錄。");
console.log("已達(dá)到最大重試次數(shù),停止重連。");
}
}
};
// 關(guān)閉 SSE 連接
const closeConnection = () => {
eventSource.close();
console.log("SSE 連接已手動關(guān)閉");
};
// 重置
const removeNotification = () => {
systemData.value = {};
managerData.value = {};
thumb.value = 0;
star.value = 0;
manager_count.value = 0;
system_count.value = 0;
email_count.value = 0;
activeTab.value = 0;
};
return {
username,
storedRole,
systemData,
managerData,
manager_count,
system_count,
email_count,
thumb,
comment,
star,
total,
activeTab,
noticeShow,
chunk,
systemNotice,
managerNotice,
userThumNotification,
userComNotification,
userStarNotification,
reportEmail,
closeConnection,
removeNotification,
initializeSSE,
initNotifications
};
},
{
persist: true
}
);到此這篇關(guān)于Vue3實(shí)現(xiàn)SSE(Server-Sent Events)連接的文章就介紹到這了,更多相關(guān)Vue3 SSE連接內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue組件中點(diǎn)擊按鈕后修改輸入框的狀態(tài)實(shí)例代碼
要求點(diǎn)擊修改按鈕之后部分輸入框由禁用狀態(tài)變?yōu)榭捎脿顟B(tài)。下面我給大家分享一段實(shí)例代碼基于vue組件中點(diǎn)擊按鈕后修改輸入框的狀態(tài),需要的的朋友參考下2017-04-04
vue+elementUI中el-radio設(shè)置默認(rèn)值方式
這篇文章主要介紹了vue+elementUI中el-radio設(shè)置默認(rèn)值方式,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-12-12
Vue3 Ref獲取真實(shí)DOM學(xué)習(xí)實(shí)戰(zhàn)
這篇文章主要為大家介紹了Vue3 Ref獲取真實(shí)DOM學(xué)習(xí)實(shí)戰(zhàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-06-06
vue3.0+echarts實(shí)現(xiàn)立體柱圖
這篇文章主要為大家詳細(xì)介紹了vue3.0+echarts實(shí)現(xiàn)立體柱圖,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09
vue監(jiān)聽頁面中的某個(gè)div的滾動事件并判斷滾動的位置
本文主要介紹了vue監(jiān)聽頁面中的某個(gè)div的滾動事件并判斷滾動的位置,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03
vue 解決uglifyjs-webpack-plugin打包出現(xiàn)報(bào)錯(cuò)的問題
這篇文章主要介紹了vue 解決uglifyjs-webpack-plugin打包出現(xiàn)報(bào)錯(cuò)的問題,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-08-08

