219 lines
6.9 KiB
JavaScript
219 lines
6.9 KiB
JavaScript
|
|
export default class WebSocketUtil {
|
|
/**
|
|
* WebSocket工具类,用于管理WebSocket连接
|
|
* @param {string} url - WebSocket服务器地址
|
|
* @param {Object} options - 配置选项
|
|
* @param {number} [options.maxReconnectCount=5] - 最大重连次数
|
|
* @param {number} [options.reconnectInterval=3000] - 重连间隔时间(ms)
|
|
* @param {number} [options.heartbeatInterval=30000] - 心跳间隔时间(ms)
|
|
* @param {string|Object} [options.heartbeatMsg='ping'] - 心跳消息
|
|
*/
|
|
constructor(url, options = {}) {
|
|
this.url = url;
|
|
this.options = options;
|
|
this.socketTask = null; // WebSocket任务实例
|
|
this.reconnectTimer = null; // 重连计时器
|
|
this.reconnectCount = 0; // 当前重连次数
|
|
this.maxReconnectCount = options.maxReconnectCount || 5; // 最大重连次数
|
|
this.reconnectInterval = options.reconnectInterval || 3000; // 重连间隔(ms)
|
|
this.heartbeatTimer = null; // 心跳计时器
|
|
this.heartbeatInterval = options.heartbeatInterval || 30000; // 心跳间隔(ms)
|
|
this.heartbeatMsg = options.heartbeatMsg || 'ping'; // 心跳消息
|
|
this.callbacks = {
|
|
open: [], // 连接打开回调
|
|
message: [], // 消息接收回调
|
|
close: [], // 连接关闭回调
|
|
error: [] // 错误处理回调
|
|
};
|
|
this.init(); // 初始化WebSocket连接
|
|
}
|
|
|
|
/**
|
|
* 初始化WebSocket连接
|
|
*/
|
|
init() {
|
|
// 创建WebSocket连接
|
|
this.socketTask = uni.connectSocket({
|
|
url: this.url,
|
|
header: this.options.header || {},
|
|
protocols: this.options.protocols || [],
|
|
success: () => {
|
|
console.log('WebSocket连接创建成功');
|
|
},
|
|
fail: (err) => {
|
|
console.error('WebSocket连接创建失败', err);
|
|
this.triggerEvent('error', err);
|
|
this.tryReconnect(); // 连接失败时尝试重连
|
|
}
|
|
});
|
|
|
|
// 监听WebSocket连接打开事件
|
|
this.socketTask.onOpen(() => {
|
|
console.log('WebSocket连接已打开');
|
|
this.reconnectCount = 0; // 重置重连计数
|
|
clearInterval(this.reconnectTimer); // 清除重连计时器
|
|
// this.startHeartbeat(); // 启动心跳机制
|
|
this.triggerEvent('open'); // 触发连接打开事件
|
|
});
|
|
|
|
// 监听WebSocket消息接收事件
|
|
this.socketTask.onMessage((res) => {
|
|
console.log('收到WebSocket消息', res);
|
|
this.triggerEvent('message', res); // 触发消息接收事件
|
|
});
|
|
|
|
// 监听WebSocket连接关闭事件
|
|
this.socketTask.onClose((res) => {
|
|
console.log('WebSocket连接已关闭', res);
|
|
clearInterval(this.heartbeatTimer); // 清除心跳计时器
|
|
this.triggerEvent('close', res); // 触发连接关闭事件
|
|
this.tryReconnect(); // 尝试重连
|
|
});
|
|
|
|
// 监听WebSocket错误事件
|
|
this.socketTask.onError((err) => {
|
|
console.error('WebSocket发生错误', err);
|
|
clearInterval(this.heartbeatTimer); // 清除心跳计时器
|
|
this.triggerEvent('error', err); // 触发错误事件
|
|
this.tryReconnect(); // 尝试重连
|
|
});
|
|
}
|
|
|
|
/**
|
|
* 注册事件回调
|
|
* @param {string} event - 事件名称(open/message/close/error)
|
|
* @param {Function} callback - 回调函数
|
|
* @returns {WebSocketUtil} - 返回当前实例,支持链式调用
|
|
*/
|
|
on(event, callback) {
|
|
if (this.callbacks[event]) {
|
|
this.callbacks[event].push(callback);
|
|
}
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* 移除事件回调
|
|
* @param {string} event - 事件名称(open/message/close/error)
|
|
* @param {Function} callback - 要移除的回调函数
|
|
* @returns {WebSocketUtil} - 返回当前实例,支持链式调用
|
|
*/
|
|
off(event, callback) {
|
|
if (this.callbacks[event]) {
|
|
this.callbacks[event] = this.callbacks[event].filter(cb => cb !== callback);
|
|
}
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* 触发事件回调
|
|
* @param {string} event - 事件名称
|
|
* @param {any} [data] - 传递给回调函数的数据
|
|
*/
|
|
triggerEvent(event, data) {
|
|
if (this.callbacks[event]) {
|
|
this.callbacks[event].forEach(callback => callback(data));
|
|
uni.$emit('socketEvent',{
|
|
type: event,
|
|
data
|
|
})
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 通过WebSocket发送消息
|
|
* @param {string|Object} message - 要发送的消息,可以是字符串或对象
|
|
* @returns {WebSocketUtil} - 返回当前实例,支持链式调用
|
|
*/
|
|
send(message) {
|
|
if (this.socketTask && this.getStatus() === 1) {
|
|
// 发送消息,对象会自动转换为JSON字符串
|
|
this.socketTask.send({
|
|
data: typeof message === 'string' ? message : JSON.stringify(message),
|
|
success: () => {
|
|
console.log('WebSocket消息发送成功');
|
|
},
|
|
fail: (err) => {
|
|
console.error('WebSocket消息发送失败', err);
|
|
this.triggerEvent('error', err);
|
|
}
|
|
});
|
|
} else {
|
|
console.error('WebSocket连接未打开,无法发送消息');
|
|
this.triggerEvent('error', new Error('WebSocket连接未打开'));
|
|
}
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* 关闭WebSocket连接
|
|
* @param {number} [code=1000] - 关闭码
|
|
* @param {string} [reason=''] - 关闭原因
|
|
* @returns {WebSocketUtil} - 返回当前实例,支持链式调用
|
|
*/
|
|
close(code = 1000, reason = '') {
|
|
if (this.socketTask) {
|
|
clearInterval(this.heartbeatTimer); // 清除心跳计时器
|
|
clearInterval(this.reconnectTimer); // 清除重连计时器
|
|
// 关闭WebSocket连接
|
|
this.socketTask.close({
|
|
code,
|
|
reason,
|
|
success: () => {
|
|
console.log('WebSocket连接正在关闭');
|
|
},
|
|
fail: (err) => {
|
|
console.error('WebSocket关闭失败', err);
|
|
this.triggerEvent('error', err);
|
|
}
|
|
});
|
|
}
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* 获取WebSocket连接状态
|
|
* @returns {number} - 连接状态:0-连接中,1-已连接,2-连接关闭中,3-已关闭,-1-未知
|
|
*/
|
|
getStatus() {
|
|
if (this.socketTask) {
|
|
try {
|
|
return this.socketTask.readyState;
|
|
} catch (e) {
|
|
console.error('获取WebSocket状态失败', e);
|
|
return -1;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
* 尝试重新连接WebSocket
|
|
*/
|
|
tryReconnect() {
|
|
if (this.reconnectCount < this.maxReconnectCount) {
|
|
clearInterval(this.reconnectTimer);
|
|
this.reconnectTimer = setTimeout(() => {
|
|
this.reconnectCount++;
|
|
console.log(`尝试重新连接WebSocket (${this.reconnectCount}/${this.maxReconnectCount})`);
|
|
this.init(); // 重新初始化WebSocket连接
|
|
}, this.reconnectInterval);
|
|
} else {
|
|
console.error('达到最大重连次数,停止尝试');
|
|
this.triggerEvent('error', new Error('达到最大重连次数'));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 启动心跳机制
|
|
*/
|
|
startHeartbeat() {
|
|
clearInterval(this.heartbeatTimer);
|
|
this.heartbeatTimer = setInterval(() => {
|
|
if (this.getStatus() === 1) {
|
|
this.send(this.heartbeatMsg); // 发送心跳消息
|
|
}
|
|
}, this.heartbeatInterval);
|
|
}
|
|
} |