詳解vue3中websocket的封裝與使用
前言:vue3+pinia項(xiàng)目
1.引入ws
yarn add ws
2.新建websocket.js類(lèi)
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類(lèi)型時(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類(lèi)
export const websocketStore = defineStore('websocket', () => {
/**
* socket推送過(guò)來(lái)的全量數(shù)據(jù),暴露出去用戶(hù)對(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)文章
vue中data數(shù)據(jù)之間如何賦值問(wèn)題
這篇文章主要介紹了vue中data數(shù)據(jù)之間如何賦值問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。2022-09-09
Vue+ElementUI項(xiàng)目使用webpack輸出MPA的方法
這篇文章主要介紹了Vue+ElementUI項(xiàng)目使用webpack輸出MPA的方法,本文圖文并茂給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-08-08
Vue 封裝防刷新考試倒計(jì)時(shí)組件的實(shí)現(xiàn)
這篇文章主要介紹了Vue 封裝防刷新考試倒計(jì)時(shí)組件的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06
基于Vue實(shí)現(xiàn)文字轉(zhuǎn)語(yǔ)音播放功能的示例代碼
這篇文章主要為大家詳細(xì)介紹了如何基于Vue實(shí)現(xiàn)文字轉(zhuǎn)語(yǔ)音播放應(yīng)用,具有美觀的界面和完整的交互功能,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2025-12-12
vue中data和data()的區(qū)別說(shuō)明
這篇文章主要介紹了vue中data和data()的區(qū)別說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03
用Axios Element實(shí)現(xiàn)全局的請(qǐng)求loading的方法
本篇文章主要介紹了用Axios Element實(shí)現(xiàn)全局的請(qǐng)求loading的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-03-03
利用Vue3和element-plus實(shí)現(xiàn)圖片上傳組件
element-plus提供了uploader組件,但是不好定制化。所以本文將利用Vue3和element-plus實(shí)現(xiàn)一個(gè)圖片上傳的組件,感興趣的可以了解一下2022-03-03
vue如何使用 Slot 分發(fā)內(nèi)容實(shí)例詳解
本篇文章主要介紹了vue如何使用 Slot 分發(fā)內(nèi)容實(shí)例詳解,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-09-09

