JavaScript的WebSocket封装类
WebSocket封装类
javascript
/**
* WebSocket 封装类
* - 支持心跳检测
* - 支持心跳超时延时重连
* - 支持断线延时重连
*/
export class SuWebSocket {
/**
* 构造函数
* @param {string} url WebSocket 地址
*/
constructor(url) {
// WebSocket 地址
this.url = url;
/**
* WebSocket 实例
* @type {WebSocket}
*/
this.handle = null;
// 心跳检测定时器
this.heartBeatTimer = null;
// 重连定时器
this.reconnectTimer = null;
// 心跳超时检测定时器
this.heartBeatTimeoutTimer = null;
// 重连间隔(毫秒)
this.reconnectDelay = 5000;
// 心跳检测间隔(毫秒)
this.heartBeatInterval = 30000;
// 心跳检测超时(毫秒)
this.heartBeatTimeout = 10000;
// 是否处于连接中
this.isConnecting = false;
// 重连次数
this.reconnectAttempts = 0;
// 是否允许重连
this.allowReconnect = true;
// 回调函数:连接成功
this.onOpenCallback = null;
// 回调函数:接收到消息
this.onMessageCallback = null;
// 回调函数:连接关闭
this.onCloseCallback = null;
// 回调函数:连接错误
this.onErrorCallback = null;
}
/**
* 设置连接成功回调
* @param {Function} callback
*/
onOpen(callback) {
this.onOpenCallback = callback;
}
/**
* 设置消息接收回调
* @param {Function} callback
*/
onMessage(callback) {
this.onMessageCallback = callback;
}
/**
* 设置连接关闭回调
* @param {Function} callback
*/
onClose(callback) {
this.onCloseCallback = callback;
}
/**
* 设置错误回调
* @param {Function} callback
*/
onError(callback) {
this.onErrorCallback = callback;
}
/**
* 设置是否允许重连
* @param {boolean} allow 是否允许重连
*/
setAllowReconnect(allow) {
this.allowReconnect = allow;
}
/**
* 建立 WebSocket 连接
*/
connect() {
if (this.isConnecting || this.isOpen()) {
return;
}
this.isConnecting = true;
this.allowReconnect = true;
this.handle = new WebSocket(this.url);
this.bindSocketEvents();
}
/**
* 绑定 WebSocket 事件
*/
bindSocketEvents() {
// 监听连接打开
this.handle.onopen = () => {
console.log('WebSocket 连接已打开');
this.isConnecting = false;
this.reconnectAttempts = 0;
this.startHeartBeat();
if (this.onOpenCallback) {
this.onOpenCallback();
}
};
// 监听消息接收
this.handle.onmessage = (res) => {
console.log('收到服务器消息:', res.data);
if (res.data === 'pong') {
this.handlePong();
return;
}
if (this.onMessageCallback) {
this.onMessageCallback(res.data);
}
};
// 监听连接关闭
this.handle.onclose = () => {
console.log('WebSocket 连接已关闭');
this.isConnecting = false;
this.stopHeartBeat();
if (this.onCloseCallback) {
this.onCloseCallback();
}
this.handleReconnect();
};
// 监听连接错误
this.handle.onerror = (err) => {
console.error('WebSocket 发生错误:', err);
this.isConnecting = false;
this.stopHeartBeat();
if (this.onErrorCallback) {
this.onErrorCallback(err);
}
this.handleReconnect();
};
}
/**
* 开始心跳检测
*/
startHeartBeat() {
this.stopHeartBeat();
this.heartBeatTimer = setInterval(() => {
this.sendPing();
}, this.heartBeatInterval);
}
/**
* 停止心跳检测
*/
stopHeartBeat() {
if (this.heartBeatTimer) {
clearInterval(this.heartBeatTimer);
this.heartBeatTimer = null;
}
// 清除心跳超时定时器
if (this.heartBeatTimeoutTimer) {
clearTimeout(this.heartBeatTimeoutTimer);
this.heartBeatTimeoutTimer = null;
}
}
/**
* 发送 ping 心跳包
*/
sendPing() {
this.send('ping');
if (this.heartBeatTimeoutTimer) {
clearTimeout(this.heartBeatTimeoutTimer);
}
// 启动心跳超时定时器
this.heartBeatTimeoutTimer = setTimeout(() => {
this.handleHeartBeatTimeout();
}, this.heartBeatTimeout);
}
/**
* 处理 pong 响应
*/
handlePong() {
console.log('收到服务器 pong 响应');
// 清除心跳超时定时器
if (this.heartBeatTimeoutTimer) {
clearTimeout(this.heartBeatTimeoutTimer);
this.heartBeatTimeoutTimer = null;
}
}
/**
* 处理心跳超时
*/
handleHeartBeatTimeout() {
console.warn('心跳超时,未收到服务器 pong 响应');
// 关闭当前连接并触发重连
this.close();
this.handleReconnect();
}
/**
* 处理重连逻辑
*/
handleReconnect() {
// 如果不允许重连,则不执行重连逻辑
if (!this.allowReconnect) {
return;
}
if (this.reconnectTimer) {
clearTimeout(this.reconnectTimer);
}
this.reconnectTimer = setTimeout(() => {
this.reconnectAttempts++;
console.log(`WebSocket 尝试重连第 ${this.reconnectAttempts} 次`);
this.connect();
}, this.reconnectDelay);
}
/**
* 关闭 WebSocket 连接
*/
close() {
if (this.reconnectTimer) {
clearTimeout(this.reconnectTimer);
this.reconnectTimer = null;
}
this.stopHeartBeat();
if (this.handle) {
this.handle.close();
this.handle = null;
}
this.isConnecting = false;
}
/**
* 发送消息
* @param {*} data
*/
send(data) {
if (this.isOpen()) {
this.handle.send(data);
} else {
console.warn('WebSocket 未连接,无法发送消息');
}
}
/**
* 销毁WebSocket实例
*/
destroy() {
// 设置不允许重连,防止在关闭过程中触发重连
this.allowReconnect = false;
this.close();
}
/**
* 获取连接状态
* @return {boolean}
*/
isOpen() {
return this.handle && this.handle.readyState === WebSocket.OPEN;
}
}
/**
* 创建 WebSocket 实例
* @param {string} url
* @return {SuWebSocket}
*/
export function makeWebSocket(url) {
return new SuWebSocket(url);
}