前言
在前端开发中,我们有时会遇到一些需要websocket的情况,而一个系统里如果有多个地方需要用到websocket,我们就会去写很多重复的处理代码,所以这边自己封装了websocket的类。
一些需要websocket的场景,比如:
1.异步等待服务状态,可以实时获取后端通过k8s创建服务的流程信息
2.web终端,可以使用websocket与后端实时同步输入与输出
3.大屏图表,一些比较重要的数据是需要查看实时的
封装思路
首先构造函数中可以设置websocket的连接地址与socket的实例等信息,传参只需要一个连接地址,因为前端并没有方法的重载,所以这些重连和心跳不是直接在构造函数添加入参,而是直接通过独立的方法手动设置
封装类代码(重连估计还有点小问题😄)
export class WebsocketManager {
constructor(url) {
// 连接地址
this.url = url;
this.socket = null;
// 心跳定时器
this.heartTimer = null;
// 重连次数
this.reconnectCount = 0;
//普通定时器
this.timer = null;
//连接开始时间
this.openTime = null;
//连接断开时间
this.closeTime = null;
}
init() {
// 初始化websocket
this.socket = new WebSocket(this.url);
this.handleSocketOpen();
this.handleSocketMessage();
this.handleSocketClose();
this.handleSocketError();
}
/**
* 建立心跳机制
* @param {*} heartbeat 是否开启心跳
* @param {*} heartbeatInterval 心跳间隔
* @param {*} heartbeatInfo 心跳发送信息
*/
setHeartbeat(heartbeat = false, heartbeatInterval = 1000, heartbeatInfo = '') {
if (heartbeat)
// 开启心跳
this.heartTimer = setInterval(() => {
this.socket.send(heartbeatInfo);
}, heartbeatInterval);
else {
// 关闭心跳
clearInterval(this.heartTimer);
this.heartTimer = null;
}
}
/**
* 建立重连机制
* @param {*} reconnect 是否重连
* @param {*} maxReconnectCount 最大重连次数
* @param {*} reconnectDelay 尝试重连延时
*/
setReconnect(reconnect = false, maxReconnectCount = 9999, reconnectDelay = 5000) {
this.reconnect = reconnect;
this.maxReconnectCount = maxReconnectCount;
this.reconnectDelay = reconnectDelay;
}
// 处理连接打开事件
handleSocketOpen() {
this.socket.onopen = (event) => {
console.log('socket open:', event);
this.openTime = new Date();
console.log('socket open time:', this.openTime);
};
}
// 处理接收到消息事件
handleSocketMessage() {
this.socket.onmessage = (event) => {
console.log('socket open:', event);
};
}
//处理连接关闭事件
handleSocketClose() {
this.socket.onclose = (event) => {
console.log('socket close:', event);
this.closeTime = new Date();
console.log('socket close time:', this.closeTime);
console.log('socket continue period:', this.closeTime - this.openTime);
// 清除心跳计时器
this.setHeartbeat(false);
// 是否支持重连
if (this.reconnect) {
//是否超过最大重连次数
if (this.reconnectCount <= this.maxReconnectCount) {
this.reconnectCount++;
this.timer = setTimeout(() => {
console.log('重连');
this.init();
}, this.reconnectDelay);
} else {
// 重置最大重连次数
this.reconnectCount = 0;
console.error('超过最大重连次数');
}
}
};
}
// 处理 WebSocket 错误事件
handleSocketError() {
this.socket.onerror = (event) => {
console.error('socket error-' + new Date(), event);
};
}
closeWebSocket() {
this.socket.close();
//清除心跳计时器
this.setHeartbeat(false);
// 重置重连次数
this.reconnectCount = 0;
}
}
使用方法
实现一个类去继承这个websocket封装类,有需要心跳或者重连机制的话可以重写init类,也可以重写接受消息的方法,如下部分vue代码示例
class DevServiceSocket extends WebsocketManager {
constructor(url) {
super(url);
}
init() {
super.init();
this.setHeartbeat(true, 60000);
}
handleSocketMessage() {
this.socket.onmessage = (event) => {
const record = JSON.parse(event.data);
handleDevSocketMessage(record);
};
}
}
let devServiceSocket = null
function initDevSocket() {
const url = 'xxx'
devServiceSocket = new DevServiceSocket(url)
devServiceSocket.init()
}
onMounted(() => {
initDevSocket()
})
onBeforeUnmount(() => {
devServiceSocket.closeWebSocket()
})