websocket在vue2中的封裝使用方式
websocket在vue2中的封裝使用
先說(shuō)需求: 頁(yè)面中有websocket連接,進(jìn)入的時(shí)候發(fā)送參數(shù)到后端,后端發(fā)送消息, 離開(kāi)頁(yè)面時(shí)發(fā)送參數(shù)至后端,后端停止發(fā)送消息,不得斷開(kāi)連接, 下一次進(jìn)入時(shí)頁(yè)面時(shí)不用再次連接。
實(shí)現(xiàn)思路
- 因?yàn)槭侨诌B接一個(gè)websocket,所以這里采用單例模式
- 也是因?yàn)榉庋b的原因,頁(yè)面中肯定是直接拿不到onmessage中返回的數(shù)據(jù), 所以這里采用發(fā)布訂閱模式來(lái)做
完整代碼在最后,不想看我廢話的可以直接扒拉了
步驟
步驟就是: 連接,頁(yè)面發(fā)送消息,接收消息,over ~
- 首先定義連接websocket的方法
export default class SocketService {
constructor(url){
this.url = url
},
connect() {
//判斷瀏覽器是否支持websocket
if (!window.WebSocket) {
return console.log("您的瀏覽器不支持WebSocket");
}
url,
//連接websocket
this.ws = new WebSocket(this.url);
//監(jiān)聽(tīng)websocket各種狀態(tài)
this.ws.onopen = () => {};
this.ws.onclose = () => {};
this.ws.onerror = () => {};
this.ws.onmessage = (e) => {};
}
}- 我們先讓socket連接上叭
export default class SocketService {
constructor(url, againConnect = true){
this.url = url
this.againConnect = againConnect;
},
ws = null; // 和服務(wù)端連接的socket對(duì)象
url; //地址
againConnect; //標(biāo)識(shí)斷開(kāi)是否重連
connected = false; // 標(biāo)識(shí)是否連接成功
sendRetryCount = 0; // 記錄重試的次數(shù)
connectRetryCount = 0; // 重新連接嘗試的次數(shù)
connect() {
//判斷瀏覽器是否支持websocket
if (!window.WebSocket) {
return console.log("您的瀏覽器不支持WebSocket");
}
url,
//連接websocket
this.ws = new WebSocket(this.url);
//監(jiān)聽(tīng)websocket各種狀態(tài)
this.ws.onopen = () => {
//連接上后所有標(biāo)識(shí)清零
this.connected = true;
this.connectRetryCount = 0;
};
this.ws.onclose = () => {
//連接關(guān)閉
this.connected = false;
this.connectRetryCount++;
if (this.againConnect) {
//重連
setTimeout(() => {
this.connect();
}, 500 * this.connectRetryCount);
} else {
//不重連的操作
sessionStorage.clear();
localStorage.clear();
message.error("登錄超時(shí)");
router.push("/");
}
};
this.ws.onerror = () => {
//連接失敗
this.connected = false;
this.connectRetryCount++;
if (this.againConnect) {
setTimeout(() => {
this.connect();
}, 500 * this.connectRetryCount);
}
};
this.ws.onmessage = (e) => {
console.log(e)
};
},
unSubscribe() {}
send(){
//發(fā)送消息的方法
}
}那么我們要怎么給后端發(fā)送消息呢,發(fā)送了消息之后我們又該怎樣才能在頁(yè)面中接收到消息呢?
subscribeList = {}; //記載回調(diào)函數(shù)
idList = [];
send(data, callback) {
//判斷此時(shí)有沒(méi)有ws
if (!this.ws) {
this.connect();
this.send(data, callback);
} else {
// 判斷此時(shí)此刻有沒(méi)有連接成功
if (this.connected) {
this.sendRetryCount = 0;
this.ws.send(JSON.stringify(data));
if (data.type === "sub") {
//存儲(chǔ)id
this.idList.push(data.id);
//存儲(chǔ)回調(diào)函數(shù),
if (!this.subscribeList[data.id]) {
this.subscribeList[data.id] = [callback];
} else {
this.subscribeList[data.id].push(callback);
}
}
} else {
this.sendRetryCount++;
setTimeout(() => {
this.send(data, callback);
}, this.sendRetryCount * 500);
}
}
}
connect(){
......
this.ws.onmessage = (e) => {
let { payload, requestId, type } = JSON.parse(e.data);
if (type === "error") {
console.log("出錯(cuò)了");
}
if (this.subscribeList[requestId]) {
if (type === "complete") {
console.log("完成了");
} else if (type === "result") {
this.subscribeList[requestId].forEach((item) =>
item.call(this, payload)
);
}
}
};
}
//銷(xiāo)毀回調(diào)函數(shù)
unSubscribe() {
//停止消息發(fā)送
this.idList.forEach((item) => {
this.send({ id: item, type: "unsub" });
delete this.subscribeList[item];
});
this.idList = [];
}1.在send方法中接收一個(gè)回調(diào)函數(shù)
- sub標(biāo)識(shí)發(fā)送消息, unsub標(biāo)識(shí)停止發(fā)送消息
- id為事件的標(biāo)識(shí)符
2.在message中調(diào)用
現(xiàn)在解決了頁(yè)面中接收消息的問(wèn)題,那么怎么保證離開(kāi)頁(yè)面,回到頁(yè)面,使用的是同一個(gè)websocket呢,如果實(shí)例化這個(gè)類(lèi)的話,那么每次進(jìn)入都會(huì)實(shí)例化SocketService,
instance = null;
static get Instance() {
if (!this.instance) {
this.instance = new SocketService(false);
}
return this.instance;
}1.es6的class中有取值函數(shù)和存值函數(shù), 具體使用請(qǐng)看這里:
2.Class 的基本語(yǔ)法 - ES6 教程 - 網(wǎng)道
- 使用getter,來(lái)拿取class中的instance,拿取的時(shí)候設(shè)置攔截該行為,判斷instance有沒(méi)有值,沒(méi)有值就實(shí)例化SocketService給instance,返回instance,
頁(yè)面中使用方式
import SocketService from "@/websocket/websocket";
mounted() {
this.ws = SocketService.Instance;
this.ws.send(
{
id: "11111",
topic: "/xxx/xxx",
parameter: {},
type: "sub",
},
this.Callback
);
}
destroyed() {
this.ws.unSubscribe();
},
methods:{
Callback(data) {
console.log(data);
},
}看到這里了,不妨給個(gè)小心心叭
在vue中的封裝
export default class SocketService {
constructor(againConnect = true, url) {
this.url = url;
this.againConnect = againConnect;
}
instance = null; //頁(yè)面中使用的SocketService實(shí)例
ws = null; // 和服務(wù)端連接的socket對(duì)象
url; //地址
againConnect; //斷開(kāi)是否重連
connected = false; // 標(biāo)識(shí)是否連接成功
sendRetryCount = 0; // 記錄重試的次數(shù)
connectRetryCount = 0; // 重新連接嘗試的次數(shù)
//單例模式保證只有一個(gè)SocketService實(shí)例
static get Instance() {
if (!this.instance) {
this.url = '......'
this.instance = new SocketService(false, url);
}
return this.instance;
}
// 定義連接服務(wù)器的方法
connect() {
// 這里判斷你的瀏覽器支不支持websocket
if (!window.WebSocket) {
return console.log("您的瀏覽器不支持WebSocket");
}
this.ws = new WebSocket(this.url);
//連接上了
this.ws.onopen = () => {
this.connected = true;
// 重置重新連接的次數(shù)
this.connectRetryCount = 0;
};
//連接關(guān)閉了,設(shè)置標(biāo)識(shí)值為false,
this.ws.onclose = () => {
this.connected = false;
this.connectRetryCount++;
if (this.againConnect) {
setTimeout(() => {
this.connect();
}, 500 * this.connectRetryCount);
} else {
sessionStorage.clear();
localStorage.clear();
message.error("登錄超時(shí)");
router.push("/");
}
};
this.ws.onerror = () => {
console.log("socket連接失敗");
this.connected = false;
this.connectRetryCount++;
if (this.againConnect) {
setTimeout(() => {
this.connect();
}, 500 * this.connectRetryCount);
}
};
this.ws.onmessage = (e) => {
let { payload, requestId } = JSON.parse(e.data);
if (this.subscribeList[requestId]) {
this.subscribeList[requestId].forEach((item) =>
item.call(this, payload)
);
}
};
}
//銷(xiāo)毀回調(diào)函數(shù)
unSubscribe() {
//停止消息發(fā)送
this.idList.forEach((item) => {
this.send({ id: item, type: "unsub" });
delete this.subscribeList[item];
});
this.idList = [];
}
subscribeList = {}; //記載回調(diào)函數(shù)
idList = [];
// 發(fā)送數(shù)據(jù)的方法
send(data, callback) {
//判斷此時(shí)有沒(méi)有ws
if (!this.ws) {
this.connect();
this.send(data, callback);
} else {
// 判斷此時(shí)此刻有沒(méi)有連接成功
if (this.connected) {
this.sendRetryCount = 0;
this.ws.send(JSON.stringify(data));
if (data.type === "sub") {
//存儲(chǔ)id
this.idList.push(data.id);
//存儲(chǔ)回調(diào)函數(shù),
if (!this.subscribeList[data.id]) {
this.subscribeList[data.id] = [callback];
} else {
this.subscribeList[data.id].push(callback);
}
}
} else {
this.sendRetryCount++;
setTimeout(() => {
this.send(data, callback);
}, this.sendRetryCount * 500);
}
}
}
}
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
VSCode Vue開(kāi)發(fā)推薦插件和VSCode快捷鍵(小結(jié))
這篇文章主要介紹了VSCode Vue開(kāi)發(fā)推薦插件和VSCode快捷鍵(小結(jié)),文中通過(guò)圖文表格介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-08-08
vue.js前后端數(shù)據(jù)交互之提交數(shù)據(jù)操作詳解
這篇文章主要介紹了vue.js前后端數(shù)據(jù)交互之提交數(shù)據(jù)操作,結(jié)合實(shí)例形式較為詳細(xì)的分析了vue.js前后端數(shù)據(jù)交互相關(guān)的表單結(jié)構(gòu)、約束規(guī)則、數(shù)據(jù)提交等相關(guān)操作技巧與注意事項(xiàng),需要的朋友可以參考下2018-04-04
詳解vue3.2中setup語(yǔ)法糖<script?lang="ts"?setup>
Vue 3.2 引入了語(yǔ)法,這是一種稍微不那么冗長(zhǎng)的聲明組件的方式,下面這篇文章主要介紹了詳解vue3.2中setup語(yǔ)法糖<script?lang="ts"setup>的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-01-01
Vue+springboot批量刪除功能實(shí)現(xiàn)代碼
這篇文章主要介紹了Vue+springboot批量刪除功能,本文通過(guò)示例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧2024-05-05
vscode配置vue下的es6規(guī)范自動(dòng)格式化詳解
這篇文章主要介紹了vscode配置vue下的es6規(guī)范自動(dòng)格式化詳解,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-03-03
vue動(dòng)態(tài)設(shè)置路由權(quán)限的主要思路
這篇文章主要給大家介紹了關(guān)于vue動(dòng)態(tài)設(shè)置路由權(quán)限的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01
vue+axios實(shí)現(xiàn)post文件下載
這篇文章主要為大家詳細(xì)介紹了vue+axios實(shí)現(xiàn)post文件下載,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-09-09

