詳解vue3中websocket的封裝與使用
前言:vue3+pinia項(xiàng)目
1.引入ws
yarn add ws
2.新建websocket.js類
let webSock = null; let global_callback = null; let isConnect = false; //連接標(biāo)識(shí) 避免重復(fù)連接 let rec; //斷線重連后,延遲5秒重新創(chuàng)建WebSocket連接 rec用來(lái)存儲(chǔ)延遲請(qǐng)求的代碼 let socketParams = { pageKey: -1 }; let isActiveClose = false; // 是否主動(dòng)關(guān)閉socket let serverPort = "8080"; // webSocket連接端口 let wsUri = "ws://" + "xxx.xx.xx.xx" + ":" + serverPort; // let serverPort = "8081"; // webSocket連接端口 // let wsUri = "ws://" + "192.168.50.156" + ":" + serverPort; function createWebSocket(callback) { if (webSock == null || Object.prototype.toString.call(webSock) !== "[object WebSocket]") { initWebSocket(callback); } } function initWebSocket(callback) { log("init webSocket"); global_callback = callback; // 初始化websocket webSock = new WebSocket(`${wsUri}?Authorization=${填寫(xiě)登錄令牌token}`); webSock.onmessage = function(e) { websocketOnMessage(e); }; webSock.onclose = function(e) { websocketClose(e); }; webSock.onopen = function() { websocketOpen(); }; // 連接發(fā)生錯(cuò)誤的回調(diào)方法 webSock.onerror = function() { websocketError(); }; } //心跳設(shè)置 const heartCheck = { timeout: 20000, //每段時(shí)間發(fā)送一次心跳包 這里設(shè)置為20s timeoutObj: null, //延時(shí)發(fā)送消息對(duì)象(啟動(dòng)心跳新建這個(gè)對(duì)象,收到消息后重置對(duì)象) start: function() { this.timeoutObj = setInterval(function() { if (isConnect) webSock.send(JSON.stringify(socketParams)); }, this.timeout); }, reset: function() { clearTimeout(this.timeoutObj); this.start(); } }; //定義重連函數(shù) let reConnect = () => { log("嘗試重新連接"); if (isConnect) return; //如果已經(jīng)連上就不在重連了 rec && clearTimeout(rec); rec = setTimeout(function() { // 延遲5秒重連 避免過(guò)多次過(guò)頻繁請(qǐng)求重連 if (!isConnect) { initWebSocket(); } }, 5000); }; // 實(shí)際調(diào)用的方法 function sendSock(agentData) { if (webSock.readyState === webSock.OPEN) { // 若是ws開(kāi)啟狀態(tài) websocketSend(agentData); } else if (webSock.readyState === webSock.CONNECTING) { // 若是 正在開(kāi)啟狀態(tài),則等待1s后重新調(diào)用 setTimeout(function() { sendSock(agentData); }, 1000); } else { // 若未開(kāi)啟 ,則等待1s后重新調(diào)用 setTimeout(function() { sendSock(agentData); }, 1000); } } function closeSock({ activeClose = false }) { log(`關(guān)閉了 activeClose = ${activeClose}`); isActiveClose = activeClose; // 清除心跳定時(shí)器 heartCheck.timeoutObj && clearTimeout(heartCheck.timeoutObj); // 清除重連定時(shí)器 rec && clearTimeout(rec); if (isActiveClose) { // 關(guān)閉socket webSock.close(); } // 初始化相關(guān)變量 webSock = null; isConnect = false; } // 數(shù)據(jù)接收 function websocketOnMessage(msg) { // global_callback(JSON.parse(msg.data)); if (!msg || !msg.data) { // 可能得情況 - 心跳機(jī)制、無(wú)關(guān)信息接收 log("收到數(shù)據(jù):空消息"); return; } log("收到數(shù)據(jù):"+ msg.data); // 收到信息為Blob類型時(shí) let result = null; if (msg.data instanceof Blob) { const reader = new FileReader(); reader.readAsText(msg.data, "UTF-8"); reader.onload = (e) => { result = JSON.parse(reader.result); //console.log("websocket收到", result); global_callback(result); }; } else { result = JSON.parse(msg.data); //console.log("websocket收到", result); global_callback(result); } } // 數(shù)據(jù)發(fā)送 function websocketSend(agentData) { log("發(fā)送數(shù)據(jù):" + agentData); webSock.send(agentData); } // 關(guān)閉 function websocketClose(e) { log("connection closed (" + e.code + ")"); if (isActiveClose) { isActiveClose = false; return; } closeSock({ activeClose: false }); // 執(zhí)行重連 reConnect(); } const websocketError = () => { log("WebSocket連接發(fā)生錯(cuò)誤"); closeSock({ activeClose: true }); // 執(zhí)行重連 reConnect(); } function websocketOpen(e) { log("連接打開(kāi)"); isConnect = true; heartCheck.start(); //發(fā)送心跳 看個(gè)人項(xiàng)目需求 } export { sendSock, createWebSocket, closeSock };
3.新建一個(gè)pinia Store類
export const websocketStore = defineStore('websocket', () => { /** * socket推送過(guò)來(lái)的全量數(shù)據(jù),暴露出去用戶對(duì)數(shù)據(jù)變更的監(jiān)聽(tīng) */ const serviceMsg = ref({}); /** * 連接webSocket init */ const init = () => { createWebSocket(global_callback); }; /** * websocket的回調(diào)函數(shù) * @param jsonMsg 表示收到的消息 */ const global_callback = (jsonMsg) => { serviceMsg.value = jsonMsg; ... ... }; /** * webSocket發(fā)送消息 * @param sendData 發(fā)送的json數(shù)據(jù) */ const send = (sendData) => { sendSock(JSON.stringify(sendData)); }; /** * 關(guān)閉webSocket */ const close = ({ isActiveClose = false }) => { closeSock({ activeClose: isActiveClose }); }; /** * 關(guān)閉后重啟socket */ const closeAndRestart = () => { close({ isActiveClose: true }); init(); }; ... ... return { init, close, closeAndRestart, serviceMsg, ... ... }; });
4.頁(yè)面中使用
// 在頁(yè)面掛載完成時(shí)啟動(dòng)websocket onMounted(() => { websocketStore().init(); }); // 使用watch函數(shù)監(jiān)聽(tīng)消息變更 watch( () => websocketStore().chatMsg, (nValue, oValue) => { // todo 界面信息更新 } );
到此這篇關(guān)于詳解vue3中websocket的封裝與使用的文章就介紹到這了,更多相關(guān)vue3 websocket內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
解決vuex刷新?tīng)顟B(tài)初始化的方法實(shí)現(xiàn)
這篇文章主要介紹了解決vuex刷新?tīng)顟B(tài)初始化的方法實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08Vue基于localStorage存儲(chǔ)信息代碼實(shí)例
這篇文章主要介紹了Vue基于localStorage存儲(chǔ)信息代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-11-11如何使用 Vue Router 的 meta 屬性實(shí)現(xiàn)多種功能
在Vue.js中,Vue Router 提供了強(qiáng)大的路由管理功能,通過(guò)meta屬性,我們可以在路由定義中添加自定義元數(shù)據(jù),以實(shí)現(xiàn)訪問(wèn)控制、頁(yè)面標(biāo)題設(shè)置、角色權(quán)限管理、頁(yè)面過(guò)渡效果,本文將總結(jié)如何使用 meta 屬性來(lái)實(shí)現(xiàn)這些常見(jiàn)的功能,感興趣的朋友一起看看吧2024-06-06Ant?Design?of?Vue的樹(shù)形控件Tree的使用及說(shuō)明
這篇文章主要介紹了Ant?Design?of?Vue的樹(shù)形控件Tree的使用及說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-10-10查看vue版本號(hào)以及vue/cli腳手架版本號(hào)方式
這篇文章主要介紹了查看vue版本號(hào)以及vue/cli腳手架版本號(hào)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-10-10vue 實(shí)現(xiàn)滾動(dòng)到底部翻頁(yè)效果(pc端)
這篇文章主要介紹了pc端vue 滾動(dòng)到底部翻頁(yè)效果,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值 ,需要的朋友可以參考下2019-07-07