一文详解websocket在vue2中的封装使用
作者:梓恒 发布时间:2024-05-02 17:08:54
标签:vue2,websocket,封装
websocket在vue2中的封装使用
先说需求: 页面中有websocket连接,进入的时候发送参数到后端,后端发送消息, 离开页面时发送参数至后端,后端停止发送消息,不得断开连接, 下一次进入时页面时不用再次连接。
实现思路:
因为是全局连接一个websocket,所以这里采用单例模式
也是因为封装的原因,页面中肯定是直接拿不到onmessage中返回的数据, 所以这里采用发布订阅模式来做
完整代码在最后,不想看我废话的可以直接扒拉了
步骤
步骤就是: 连接,页面发送消息,接收消息,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);
//监听websocket各种状态
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; // 和服务端连接的socket对象
url; //地址
againConnect; //标识断开是否重连
connected = false; // 标识是否连接成功
sendRetryCount = 0; // 记录重试的次数
connectRetryCount = 0; // 重新连接尝试的次数
connect() {
//判断浏览器是否支持websocket
if (!window.WebSocket) {
return console.log("您的浏览器不支持WebSocket");
}
url,
//连接websocket
this.ws = new WebSocket(this.url);
//监听websocket各种状态
this.ws.onopen = () => {
//连接上后所有标识清零
this.connected = true;
this.connectRetryCount = 0;
};
this.ws.onclose = () => {
//连接关闭
this.connected = false;
this.connectRetryCount++;
if (this.againConnect) {
//重连
setTimeout(() => {
this.connect();
}, 500 * this.connectRetryCount);
} else {
//不重连的操作
sessionStorage.clear();
localStorage.clear();
message.error("登录超时");
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(){
//发送消息的方法
}
}
那么我们要怎么给后端发送消息呢,发送了消息之后我们又该怎样才能在页面中接收到消息呢?
在send方法中接收一个回调函数,
在message中调用,
subscribeList = {}; //记载回调函数
idList = [];
send(data, callback) {
//判断此时有没有ws
if (!this.ws) {
this.connect();
this.send(data, callback);
} else {
// 判断此时此刻有没有连接成功
if (this.connected) {
this.sendRetryCount = 0;
this.ws.send(JSON.stringify(data));
if (data.type === "sub") {
//存储id
this.idList.push(data.id);
//存储回调函数,
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("出错了");
}
if (this.subscribeList[requestId]) {
if (type === "complete") {
console.log("完成了");
} else if (type === "result") {
this.subscribeList[requestId].forEach((item) =>
item.call(this, payload)
);
}
}
};
}
//销毁回调函数
unSubscribe() {
//停止消息发送
this.idList.forEach((item) => {
this.send({ id: item, type: "unsub" });
delete this.subscribeList[item];
});
this.idList = [];
}
sub标识发送消息, unsub标识停止发送消息
id为事件的标识符
现在解决了页面中接收消息的问题,那么怎么保证离开页面,回到页面,使用的是同一个websocket呢,如果实例化这个类的话,那么每次进入都会实例化SocketService,
es6的class中有取值函数和存值函数, 具体使用请看这里:
Class 的基本语法 - ES6 教程 - 网道 (wangdoc.com)
instance = null;
static get Instance() {
if (!this.instance) {
this.instance = new SocketService(false);
}
return this.instance;
}
使用getter,来拿取class中的instance,拿取的时候设置拦截该行为,判断instance有没有值,没有值就实例化SocketService给instance,返回instance,
页面中使用方式
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);
},
}
看到这里了,不妨给个小心心叭
在vue中的封装
export default class SocketService {
constructor(againConnect = true, url) {
this.url = url;
this.againConnect = againConnect;
}
instance = null; //页面中使用的SocketService实例
ws = null; // 和服务端连接的socket对象
url; //地址
againConnect; //断开是否重连
connected = false; // 标识是否连接成功
sendRetryCount = 0; // 记录重试的次数
connectRetryCount = 0; // 重新连接尝试的次数
//单例模式保证只有一个SocketService实例
static get Instance() {
if (!this.instance) {
this.url = '......'
this.instance = new SocketService(false, url);
}
return this.instance;
}
// 定义连接服务器的方法
connect() {
// 这里判断你的浏览器支不支持websocket
if (!window.WebSocket) {
return console.log("您的浏览器不支持WebSocket");
}
this.ws = new WebSocket(this.url);
//连接上了
this.ws.onopen = () => {
this.connected = true;
// 重置重新连接的次数
this.connectRetryCount = 0;
};
//连接关闭了,设置标识值为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("登录超时");
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)
);
}
};
}
//销毁回调函数
unSubscribe() {
//停止消息发送
this.idList.forEach((item) => {
this.send({ id: item, type: "unsub" });
delete this.subscribeList[item];
});
this.idList = [];
}
subscribeList = {}; //记载回调函数
idList = [];
// 发送数据的方法
send(data, callback) {
//判断此时有没有ws
if (!this.ws) {
this.connect();
this.send(data, callback);
} else {
// 判断此时此刻有没有连接成功
if (this.connected) {
this.sendRetryCount = 0;
this.ws.send(JSON.stringify(data));
if (data.type === "sub") {
//存储id
this.idList.push(data.id);
//存储回调函数,
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);
}
}
}
}
来源:https://juejin.cn/post/7207707775772917818
0
投稿
猜你喜欢
- 相信很多小伙伴想着自己的移动端项目能够自动转换为rem,这才符合前端的潮流,如果用自己手写或者编辑器插件来改动十分不方便还容易出错,我在网上
- 主要介绍常用的MySQL命令,包括连接数据库,修改密码,管理用户,操作数据库,操作数据表,数据库备份等,每个命令都配有实例说明,让大家更容易
- 接口(python 中的协议)的多种不同的实现方式即为多态。多态的作用,就是为了类在继承和派生的时候,保证使用“家谱”中任一类的实例的某一属
- KindEditor简介: KindEditor是一套开源的在线HTML编辑器,主要用于让用户在网站上获得所见即所得编辑效果,开发人员可以用
- 使用诸如Lock、RLock、Semphore之类的锁原语时,必须多加小心,锁的错误使用很容易导致死锁或相互竞争。依赖锁的代码应该保证当出现
- 本文实例讲述了Python简单实现网页内容抓取功能。分享给大家供大家参考,具体如下:使用模块:import urllib2 import u
- 我的电脑本来是有手动CMake+make安装的OpenCV3的,以及系统自带的python2.x,但是现在想用python3+OpenCV3
- 前言大家好,我叫善念。这是我的第二篇博客,也是第一篇技术博客,希望大家多多支持,让我更加有动力去更新一些python爬虫类的案例教程。开始确
- 要读懂这些代码主要是要了解ASP中操作二进制数据的对象ADODB.Stream!本程序主要用的就是Adodb.Stream,如果你有这个基础
- Linux系统下调用动态库(.so) 1、linuxany.c代码如下: #include "stdio.h"
- ''推拉门''动效也可以称作"手风琴"效果,大多数效果实现的思路基本是一样的,下面介绍两
- MySQL8服务无法正常启动的解决(1053错误)第一种方法初始化后在Mysql的根目录会生成 data 数据库文件夹,如果启动服务失败,很
- MySQL Order By keyword是用来给记录中的数据进行分类的。MySQL Order By Keyword根据关键词分类ORD
- 拉取网易蜂巢的mysql-server:5.6docker pull hub.c.163.com/nce2/mysql:5.6创建mysql
- TTS简介TTS(Text To Speech)是一种语音合成技术,可以让机器将输入文本以语音的方式播放出来,实现机器说话的效果。TTS分成
- 本文实例为大家分享了python3使用matplotlib绘制条形图的具体代码,供大家参考,具体内容如下绘制竖状条形图代码from matp
- 队列和优先队列(Priority Queue)队列是一种可以完成插入和删除的数据结构。普通队列是先进先出(FIFO), 即先插入的先被删除。
- vue中引入html静态页面功能:系统中需增加帮助中心页面,由于页面较长,需要实现锚点定位跳转。1、开始用的路由方式,首先在router文件
- vue 中的 $slot以前一直不知到这个东西,后来发现 vue api 中 藏着很多的 很神奇的 api,比如这个具名插槽很好理解,但是那
- 本文实例为大家分享了python实现文件批量重命名的具体代码,供大家参考,具体内容如下代码:# -*- coding:utf-8 -*-im