概要
前端小伙伴使用uni-app開(kāi)發(fā)長(zhǎng)連接通信的時(shí)候都會(huì)有以下疑問(wèn)
- 在網(wǎng)上搜到的封裝socket都沒(méi)講怎么全局公用一個(gè)呢?
- 同一個(gè) 子協(xié)議或者我我們叫type類(lèi)型型我想在兩個(gè)頁(yè)面都接受使用怎么做呢?
目前能搜到的socket 封裝好像都沒(méi)講清楚這個(gè)東西,或者壓根沒(méi)考慮下面給大家詳細(xì)介紹下我封裝的方法 大家拿去就可以用。代碼在最后了
初始化 創(chuàng)建連接
- 在合適的場(chǎng)景下創(chuàng)建 Socket 連接
- 初始化后所有頁(yè)面均可使用
import socket from "@/components/lvSocket.js"
onLoad(()=>{ // 假設(shè)在onLoad周期需要初始化
socket.connect();// 初始化 全局只需初始化一次
})
onUnload(()=>{
socket.clearClose();// 關(guān)閉長(zhǎng)連接根據(jù)需要使用
})
接收事件
注意 type等于all時(shí)接收所有類(lèi)型參數(shù)
import socket from "@/components/lvSocket.js"
onLoad(()=>{ // 假設(shè)在onLoad周期需要初始化
// 發(fā)送消息
socket.send({
"type": "msgList",// 傳輸類(lèi)型
"payLoad": {傳輸內(nèi)容}
});
socket.on("hei",shjian);// type=hei:接受hei類(lèi)型參數(shù)
socket.on("hei",()=>{console.log('hei收到了')});// type=hei:接受hei類(lèi)型參數(shù)
socket.on("heier",()=>{console.log('er收到了')});// type=heier:接受hei類(lèi)型參數(shù)
socket.on("all",jieshouAll);// type=all:接受所有參數(shù) all為type類(lèi)型關(guān)鍵字
})
const shjian = (meg)=>{
console.log('頁(yè)面收到hei數(shù)據(jù)',meg)
}
const jieshouAll = (meg)=>{
console.log('服務(wù)端返回的所有數(shù)據(jù)都能接收到',meg)
}
// 頁(yè)面卸載清除事件回調(diào)
onUnload(()=>{
socket.off();// 清空所有回調(diào)
socket.off('hei');// 清除某個(gè)類(lèi)型所有回調(diào)
socket.off('hei',jieshou);// 清除某個(gè)類(lèi)型中某個(gè)回調(diào)
})
示例
在兩個(gè)頁(yè)面 接受同一個(gè)類(lèi)型 也是互不影響的。 清除的時(shí)候別誤刪了其他事件哦
import socket from "@/components/lvSocket.js"
// index 頁(yè)面
onLoad(()=>{
socket.connect();// 初始化 全局只需初始化一次
socket.on("hei",jieshou);// type=hei:接受hei類(lèi)型參數(shù)
socket.on("all",jieshouAll);// type=all:接受所有參數(shù) all為type類(lèi)型關(guān)鍵字
})
const jieshou = (meg)=>{
console.log('頁(yè)面收到數(shù)據(jù)',meg)
socket.send({type:"pingaaaaa"});// 發(fā)送消息
}
const jieshouAll = (meg)=>{
console.log('服務(wù)端返回的所有數(shù)據(jù)都能接收到',meg)
}
// 頁(yè)面卸載清除事件回調(diào)
onUnload(()=>{
socket.off();// 清空所有回調(diào)
socket.off('hei');// 清除某個(gè)類(lèi)型所有回調(diào)
socket.off('hei',jieshou);// 清除某個(gè)類(lèi)型中某個(gè)回調(diào)
socket.clearClose();// 關(guān)閉長(zhǎng)連接根據(jù)需要使用
})
// home頁(yè)面
onLoad(()=>{
socket.on("bookList",getBookList);// 接受參數(shù)
})
const getBookList = (meg)=>{
console.log('頁(yè)面收到數(shù)據(jù)',meg)
}
// 頁(yè)面卸載清除事件回調(diào)
onUnload(()=>{
socket.off('bookList');// 清除某個(gè)類(lèi)型所有回調(diào)
})
js代碼
在 src/components 路徑下創(chuàng)建 lvSocket.js 粘貼如下代碼到文件中
vue2使用請(qǐng)注意this指向問(wèn)題
文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-543478.html
/*
假設(shè)后端響應(yīng)數(shù)據(jù)類(lèi)型是這樣的
{
type:'msglist',
"payload":{
... 數(shù)據(jù)在這里
}
}
*/
/***
* @description: WebSocket 單例模式
* @author: lvhao
*/
class Socket {
constructor() {
this.socket = null;// socket實(shí)例
this.isConnect = false;// 是否連接成功
this.reconnectCount = 0;// 重連接次數(shù)
this.reconnectTimer = null;// 重連定時(shí)器
this.url = `ws://192.168.28.38:3000`
this.isHandClose = false;// 是否是手動(dòng)關(guān)閉
// 心跳定時(shí)器
this.heartbeatInterval = null;
// 收集事件綁定類(lèi)型
this._map = new Map();
// 收集未連接成功要發(fā)送的消息
this._sendArr = [];
}
// 連接
connect() {
if (this.socket) return;// 正在連接
const Token = uni.getStorageSync('Token');
this.socket = uni.connectSocket({
url:this.url,
header: {
"wsToken": `Bearer ${Token}`,
},
complete: ()=> {},
multiple:true,
})
// 連接成功
this.socket.onOpen(()=>{
console.log("連接成功")
this._onOpen();
})
// Socket 連接關(guān)閉事件
this.socket.onClose(() => {
console.log("連接關(guān)閉了")
this._onClose();
});
// 監(jiān)聽(tīng) Socket 錯(cuò)誤事件
this.socket.onError((err) => {
console.log("Socket報(bào)錯(cuò)了",err)
this._onError();
});
// 監(jiān)聽(tīng) WebSocket 接受到服務(wù)器的消息事件
this.socket.onMessage((meg)=>{
this._onMessage(meg)
});
}
// 連接成功 重置參數(shù)
_onOpen() {
this.isConnect = true;// 是否連接成功
this.reconnectCount = 0;// 重置重連次數(shù)
clearTimeout(this.reconnectTimer);// 清空重連定時(shí)器
this.isHandClose = false;// 是否是手動(dòng)關(guān)閉
this._heartbeat();// 開(kāi)啟心跳
// 未發(fā)送的消息全部發(fā)送
this._sendArr.forEach(item=>{
this.send(item);// 發(fā)送消息
})
this._sendArr = [];
}
// 監(jiān)聽(tīng) WebSocket 連接關(guān)閉事件
_onClose() {
this.socket = null;// 清空soket
this.isConnect = false;// 是否連接成功
this._clearHeartbeat();// 關(guān)閉心跳
this._reconnect();// 重新連接
}
// 監(jiān)聽(tīng) WebSocket 錯(cuò)誤事件
_onError() {
}
// 監(jiān)聽(tīng) WebSocket 接受到服務(wù)器的消息事件
_onMessage(meg) {
let data = JSON.parse(meg.data);// 收到的數(shù)據(jù)
let receiveType = data.type;// 收到的type類(lèi)型
// 觸發(fā)對(duì)應(yīng)type類(lèi)型事件 接受type為all時(shí)所有事件都會(huì)觸發(fā)
for (let entry of this._map.entries()) {
if(entry[1] === receiveType || entry[1] === 'all' ){
entry[0](data.payLoad)
}
}
}
// 自動(dòng)重連
_reconnect() {
if(this.isHandClose)return;// 手動(dòng)關(guān)閉不重連
if(this.socket)return;// 正在連接不處理
if (this.reconnectCount < 10) {
this.reconnectCount++;
this.reconnectTimer = setTimeout(() => {
console.log(`WebSocket 重連中,第 ${this.reconnectCount} 次嘗試...`);
this.connect();//連接
}, 5000);
} else {
console.log('WebSocket 重連失?。?);
}
}
// 開(kāi)啟心跳
_heartbeat(){
this._clearHeartbeat();// 關(guān)閉心跳
// 心跳10000ms發(fā)送一次
this.heartbeatInterval = setInterval(()=>{
this.send({type:'ping', "payLoad": {"ts": new Date().getTime()}})//心跳內(nèi)容
},10000)
}
// 關(guān)閉心跳
_clearHeartbeat(){
clearInterval(this.heartbeatInterval)
}
// 發(fā)送消息
send(data) {
// 當(dāng)前未連接記錄內(nèi)容 隊(duì)列中沒(méi)有才放入 心跳除外
if(!this.isConnect && data.type !== "ping" ){
const hasEqualItem = this._sendArr.some(item => JSON.stringify(item) == JSON.stringify(data));
if (!hasEqualItem) {
this._sendArr.push(data);
}
return;
}
this.socket.send({'data':JSON.stringify(data)});
}
// 接受信息 type 類(lèi)型 fn 回調(diào)函數(shù)
on(type,fn=()=>{}){
this._map.set(fn,type);
}
// 關(guān)閉接受參數(shù)
off(type,fn){// 關(guān)閉參數(shù)
if(arguments.length === 0){
// 清除全部
this._map.clear();
}else if(arguments.length === 1){
// 清除某個(gè)事件類(lèi)型整體
this._map.forEach((value, key) => {
if (value === type) {
this._map.delete(key);
}
});
}else{
// 清除某個(gè)事件類(lèi)型中某個(gè)回調(diào)
if(this._map.get(fn) === type){
this._map.delete(fn)
}
}
}
// 關(guān)閉
clearClose() {
this.isHandClose = true;// 手動(dòng)關(guān)閉
clearTimeout(this.reconnectTimer);// 清空重連定時(shí)器
if(this.socket && "close" in this.socket){
this.socket.close(); // 關(guān)閉soket
}
}
}
export default new Socket()
自定義修改說(shuō)明
- 后端參數(shù)
代碼開(kāi)頭有提到默認(rèn)后端給到的數(shù)據(jù)為 { type:'msglist',// 你和后端定義的數(shù)據(jù)type類(lèi)型 "data":{ "key":"value",// 這個(gè)type類(lèi)型對(duì)應(yīng)的數(shù)據(jù) ... } } 如果數(shù)據(jù)有修改。修改_onMessage函數(shù)修改傳入你們定義的數(shù)據(jù)即可
- 心跳
修改代碼中_heartbeat函數(shù) 修改心跳內(nèi)容和心跳間隔時(shí)間即可
- 重連
默認(rèn)最多重連10次 10次都失敗就不會(huì)重新連接了 默認(rèn)重連間隔時(shí)間5秒 只有連接失敗 或者服務(wù)報(bào)錯(cuò)才會(huì)重新連接 我們手動(dòng)關(guān)閉連接是不會(huì)重新連接的放心使用 修改_reconnect函數(shù)中的10 為你想要的重連次數(shù) 修改_reconnect函數(shù)中的5000 為你想要的重連間隔時(shí)間
小結(jié)
可以根據(jù)自己的需要對(duì)其進(jìn)行魔改。 不懂的地方可以聯(lián)系我?guī)痛蠹掖鹨?。v:H1274714546
歡迎有更好方案的小伙伴評(píng)論。分享轉(zhuǎn)載,請(qǐng)注明來(lái)源哦~文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-543478.html
到了這里,關(guān)于uni-app vue3 封裝socket 兼容微信小程序 釘釘小程序 H5 App 全局唯一的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!