概要
前端小伙伴使用uni-app开发长连接通信的时候都会有以下疑问
- 在网上搜到的封装socket都没讲怎么全局公用一个呢?
- 同一个 子协议或者我我们叫type类型型我想在两个页面都接受使用怎么做呢?
目前能搜到的socket 封装好像都没讲清楚这个东西,或者压根没考虑下面给大家详细介绍下我封装的方法 大家拿去就可以用。代码在最后了
初始化 创建连接
- 在合适的场景下创建 Socket 连接
- 初始化后所有页面均可使用
import socket from "@/components/lvSocket.js"
onLoad(()=>{ // 假设在onLoad周期需要初始化
socket.connect();// 初始化 全局只需初始化一次
})
onUnload(()=>{
socket.clearClose();// 关闭长连接根据需要使用
})
接收事件
注意 type等于all时接收所有类型参数
import socket from "@/components/lvSocket.js"
onLoad(()=>{ // 假设在onLoad周期需要初始化
// 发送消息
socket.send({
"type": "msgList",// 传输类型
"payLoad": {传输内容}
});
socket.on("hei",shjian);// type=hei:接受hei类型参数
socket.on("hei",()=>{console.log('hei收到了')});// type=hei:接受hei类型参数
socket.on("heier",()=>{console.log('er收到了')});// type=heier:接受hei类型参数
socket.on("all",jieshouAll);// type=all:接受所有参数 all为type类型关键字
})
const shjian = (meg)=>{
console.log('页面收到hei数据',meg)
}
const jieshouAll = (meg)=>{
console.log('服务端返回的所有数据都能接收到',meg)
}
// 页面卸载清除事件回调
onUnload(()=>{
socket.off();// 清空所有回调
socket.off('hei');// 清除某个类型所有回调
socket.off('hei',jieshou);// 清除某个类型中某个回调
})
示例
在两个页面 接受同一个类型 也是互不影响的。 清除的时候别误删了其他事件哦
import socket from "@/components/lvSocket.js"
// index 页面
onLoad(()=>{
socket.connect();// 初始化 全局只需初始化一次
socket.on("hei",jieshou);// type=hei:接受hei类型参数
socket.on("all",jieshouAll);// type=all:接受所有参数 all为type类型关键字
})
const jieshou = (meg)=>{
console.log('页面收到数据',meg)
socket.send({type:"pingaaaaa"});// 发送消息
}
const jieshouAll = (meg)=>{
console.log('服务端返回的所有数据都能接收到',meg)
}
// 页面卸载清除事件回调
onUnload(()=>{
socket.off();// 清空所有回调
socket.off('hei');// 清除某个类型所有回调
socket.off('hei',jieshou);// 清除某个类型中某个回调
socket.clearClose();// 关闭长连接根据需要使用
})
// home页面
onLoad(()=>{
socket.on("bookList",getBookList);// 接受参数
})
const getBookList = (meg)=>{
console.log('页面收到数据',meg)
}
// 页面卸载清除事件回调
onUnload(()=>{
socket.off('bookList');// 清除某个类型所有回调
})
js代码
在 src/components 路径下创建 lvSocket.js 粘贴如下代码到文件中
vue2使用请注意this指向问题
文章来源:https://www.toymoban.com/news/detail-543478.html
/*
假设后端响应数据类型是这样的
{
type:'msglist',
"payload":{
... 数据在这里
}
}
*/
/***
* @description: WebSocket 单例模式
* @author: lvhao
*/
class Socket {
constructor() {
this.socket = null;// socket实例
this.isConnect = false;// 是否连接成功
this.reconnectCount = 0;// 重连接次数
this.reconnectTimer = null;// 重连定时器
this.url = `ws://192.168.28.38:3000`
this.isHandClose = false;// 是否是手动关闭
// 心跳定时器
this.heartbeatInterval = null;
// 收集事件绑定类型
this._map = new Map();
// 收集未连接成功要发送的消息
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 连接关闭事件
this.socket.onClose(() => {
console.log("连接关闭了")
this._onClose();
});
// 监听 Socket 错误事件
this.socket.onError((err) => {
console.log("Socket报错了",err)
this._onError();
});
// 监听 WebSocket 接受到服务器的消息事件
this.socket.onMessage((meg)=>{
this._onMessage(meg)
});
}
// 连接成功 重置参数
_onOpen() {
this.isConnect = true;// 是否连接成功
this.reconnectCount = 0;// 重置重连次数
clearTimeout(this.reconnectTimer);// 清空重连定时器
this.isHandClose = false;// 是否是手动关闭
this._heartbeat();// 开启心跳
// 未发送的消息全部发送
this._sendArr.forEach(item=>{
this.send(item);// 发送消息
})
this._sendArr = [];
}
// 监听 WebSocket 连接关闭事件
_onClose() {
this.socket = null;// 清空soket
this.isConnect = false;// 是否连接成功
this._clearHeartbeat();// 关闭心跳
this._reconnect();// 重新连接
}
// 监听 WebSocket 错误事件
_onError() {
}
// 监听 WebSocket 接受到服务器的消息事件
_onMessage(meg) {
let data = JSON.parse(meg.data);// 收到的数据
let receiveType = data.type;// 收到的type类型
// 触发对应type类型事件 接受type为all时所有事件都会触发
for (let entry of this._map.entries()) {
if(entry[1] === receiveType || entry[1] === 'all' ){
entry[0](data.payLoad)
}
}
}
// 自动重连
_reconnect() {
if(this.isHandClose)return;// 手动关闭不重连
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 重连失败!');
}
}
// 开启心跳
_heartbeat(){
this._clearHeartbeat();// 关闭心跳
// 心跳10000ms发送一次
this.heartbeatInterval = setInterval(()=>{
this.send({type:'ping', "payLoad": {"ts": new Date().getTime()}})//心跳内容
},10000)
}
// 关闭心跳
_clearHeartbeat(){
clearInterval(this.heartbeatInterval)
}
// 发送消息
send(data) {
// 当前未连接记录内容 队列中没有才放入 心跳除外
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 类型 fn 回调函数
on(type,fn=()=>{}){
this._map.set(fn,type);
}
// 关闭接受参数
off(type,fn){// 关闭参数
if(arguments.length === 0){
// 清除全部
this._map.clear();
}else if(arguments.length === 1){
// 清除某个事件类型整体
this._map.forEach((value, key) => {
if (value === type) {
this._map.delete(key);
}
});
}else{
// 清除某个事件类型中某个回调
if(this._map.get(fn) === type){
this._map.delete(fn)
}
}
}
// 关闭
clearClose() {
this.isHandClose = true;// 手动关闭
clearTimeout(this.reconnectTimer);// 清空重连定时器
if(this.socket && "close" in this.socket){
this.socket.close(); // 关闭soket
}
}
}
export default new Socket()
自定义修改说明
- 后端参数
代码开头有提到默认后端给到的数据为 { type:'msglist',// 你和后端定义的数据type类型 "data":{ "key":"value",// 这个type类型对应的数据 ... } } 如果数据有修改。修改_onMessage函数修改传入你们定义的数据即可
- 心跳
修改代码中_heartbeat函数 修改心跳内容和心跳间隔时间即可
- 重连
默认最多重连10次 10次都失败就不会重新连接了 默认重连间隔时间5秒 只有连接失败 或者服务报错才会重新连接 我们手动关闭连接是不会重新连接的放心使用 修改_reconnect函数中的10 为你想要的重连次数 修改_reconnect函数中的5000 为你想要的重连间隔时间
小结
可以根据自己的需要对其进行魔改。 不懂的地方可以联系我帮大家答疑。v:H1274714546
欢迎有更好方案的小伙伴评论。分享转载,请注明来源哦~文章来源地址https://www.toymoban.com/news/detail-543478.html
到了这里,关于uni-app vue3 封装socket 兼容微信小程序 钉钉小程序 H5 App 全局唯一的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!