Vue3實現(xiàn)SSE(Server-Sent?Events)連接
在現(xiàn)代 web 開發(fā)中,Server-Sent Events (SSE) 是一種輕量級的技術(shù),允許服務(wù)器通過 HTTP 持久連接向客戶端推送實時更新。在本文中,我們將探討如何在 Vue 3 應(yīng)用中實現(xiàn) SSE 連接,并處理接收到的消息。
什么是 SSE
SSE 是一種允許服務(wù)器向瀏覽器推送事件的技術(shù)。與 WebSocket 不同,SSE 是單向的:服務(wù)器可以向客戶端發(fā)送數(shù)據(jù),而客戶端不能直接向服務(wù)器發(fā)送數(shù)據(jù)。SSE 適用于需要實時更新的應(yīng)用,比如聊天應(yīng)用、通知系統(tǒng)和實時數(shù)據(jù)監(jiān)控。
核心代碼示例
let retryCount = 0; const maxRetries = 5; // 最大重試次數(shù) const maxRetryDelay = 30000; // 最大重連時間,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: // 暫時擱置,用其他方法代替 if (storedRole.value !== "user") { reportEmail(); } break; default: console.warn("未知通知類型:", chunk.value.notice_type); } showNotify(); }; // 監(jiān)聽錯誤事件 eventSource.onerror = () => { console.error("SSE 連接發(fā)生錯誤,嘗試重連..."); 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 ); // 計算重連延遲 setTimeout(initializeSSE, retryDelay); } else { showToast("網(wǎng)絡(luò)連接不穩(wěn)定,請檢查網(wǎng)絡(luò)或重新登錄。"); console.log("已達到最大重試次數(shù),停止重連。"); } } };
舉例:全局狀態(tài)管理消息總數(shù)
假設(shè)我們有三種通知類型:
點贊、評論、收藏
在userStore中進行全局狀態(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; // 最大重連時間,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); // 互動通知 // 默認活躍的tab欄 const activeTab = ref(0); // 總數(shù) // 使用計算屬性動態(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("獲取通知時發(fā)生錯誤:", error); } }; // 獲取系統(tǒng)消息 const systemNotice = () => { fetchNotificationCount(getSystemNotification, systemData, system_count); console.log(system_count.value); }; // 獲取管理員消息 const managerNotice = () => { fetchNotificationCount( getManagerNotification, managerData, manager_count ); }; // 獲取點贊通知的未讀消息數(shù)量 const userThumNotification = () => { fetchNotificationCount(getUserThumNotification, null, thumb); }; // 獲取評論通知的未讀消息數(shù)量 const userComNotification = () => { fetchNotificationCount(getUserComNotification, null, comment); }; // 獲取收藏通知的未讀消息數(shù)量 const userStarNotification = () => { fetchNotificationCount(getUserStarNotification, null, star); }; // 獲取舉報郵箱消息 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: // 暫時擱置,用其他方法代替 if (storedRole.value !== "user") { reportEmail(); } break; default: console.warn("未知通知類型:", chunk.value.notice_type); } showNotify(); }; // 監(jiān)聽錯誤事件 eventSource.onerror = () => { console.error("SSE 連接發(fā)生錯誤,嘗試重連..."); 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 ); // 計算重連延遲 setTimeout(initializeSSE, retryDelay); } else { showToast("網(wǎng)絡(luò)連接不穩(wěn)定,請檢查網(wǎng)絡(luò)或重新登錄。"); console.log("已達到最大重試次數(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實現(xiàn)SSE(Server-Sent Events)連接的文章就介紹到這了,更多相關(guān)Vue3 SSE連接內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue在取對象長度length時候出現(xiàn)undefined的解決
這篇文章主要介紹了vue在取對象長度length時候出現(xiàn)undefined的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-06-06實例詳解Vue項目使用eslint + prettier規(guī)范代碼風(fēng)格
這篇文章主要介紹了Vue項目使用eslint + prettier規(guī)范代碼風(fēng)格,本文通過實例代碼給大家介紹的非常詳細,需要的朋友可以參考下2018-08-08Vue關(guān)于數(shù)據(jù)綁定出錯解決辦法
這篇文章主要介紹了Vue關(guān)于數(shù)據(jù)綁定出錯解決辦法的相關(guān)資料,需要的朋友可以參考下2017-05-05Vue3中導(dǎo)入和使用組件幾種常見方法(.vue文件)
組件是Vue.js最強大的功能之一, 組件可以擴展HTML元素,封裝可重用的代碼,下面這篇文章主要介紹了Vue3中導(dǎo)入和使用組件幾種常見方法,文中通過代碼介紹的非常詳細,需要的朋友可以參考下2024-09-09Vue Element前端應(yīng)用開發(fā)之開發(fā)環(huán)境的準備工作
這篇文章主要介紹了Vue Element前端應(yīng)用開發(fā)之開發(fā)環(huán)境的準備工作,對Vue感興趣的同學(xué),可以來學(xué)習(xí)一下2021-05-05vue-resource請求實現(xiàn)http登錄攔截或者路由攔截的方法
這篇文章主要介紹了vue-resource請求實現(xiàn)http登錄攔截或者路由攔截的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-07-07