117 lines
3.5 KiB
JavaScript
117 lines
3.5 KiB
JavaScript
class WebSocketClient {
|
||
constructor(url) {
|
||
this.url = url;
|
||
this.socket = null;
|
||
this.connected = false;
|
||
this.reconnecting = false;
|
||
this.reconnectInterval = 3000; // 重连间隔(ms)
|
||
this.maxReconnectAttempts = 10; // 最大重连次数
|
||
this.reconnectAttempts = 0;
|
||
this.messageQueue = []; // 消息队列
|
||
|
||
// 事件回调
|
||
this.onConnect = null;
|
||
this.onMessage = null;
|
||
this.onClose = null;
|
||
this.onError = null;
|
||
}
|
||
|
||
// 连接WebSocket服务器
|
||
connect() {
|
||
if (this.socket && (this.socket.readyState === WebSocket.CONNECTING || this.socket.readyState === WebSocket.OPEN)) {
|
||
return;
|
||
}
|
||
|
||
this.socket = new WebSocket(this.url);
|
||
|
||
this.socket.onopen = (event) => {
|
||
this.connected = true;
|
||
this.reconnecting = false;
|
||
this.reconnectAttempts = 0;
|
||
console.log('WebSocket连接已建立');
|
||
|
||
// 发送队列中的所有消息
|
||
this._sendQueuedMessages();
|
||
|
||
if (typeof this.onConnect === 'function') {
|
||
this.onConnect(event);
|
||
}
|
||
};
|
||
|
||
this.socket.onmessage = (event) => {
|
||
console.log('收到消息:', event.data);
|
||
this.onMessage(event.data);
|
||
};
|
||
|
||
this.socket.onclose = (event) => {
|
||
this.connected = false;
|
||
console.log('WebSocket连接已关闭,代码:', event.code, '原因:', event.reason);
|
||
|
||
if (typeof this.onClose === 'function') {
|
||
this.onClose(event);
|
||
}
|
||
|
||
// 非主动关闭时尝试重连
|
||
if (!this.reconnecting && event.code !== 1000) {
|
||
this._scheduleReconnect();
|
||
}
|
||
};
|
||
|
||
this.socket.onerror = (error) => {
|
||
console.error('WebSocket错误:', error);
|
||
if (typeof this.onError === 'function') {
|
||
this.onError(error);
|
||
}
|
||
};
|
||
}
|
||
|
||
// 发送消息
|
||
send(message) {
|
||
if (this.connected && this.socket.readyState === WebSocket.OPEN) {
|
||
this.socket.send(message);
|
||
} else {
|
||
// 连接未建立,将消息加入队列
|
||
this.messageQueue.push(message);
|
||
if (!this.reconnecting) {
|
||
this._scheduleReconnect();
|
||
}
|
||
}
|
||
}
|
||
|
||
// 关闭连接
|
||
close(code = 1000, reason = '') {
|
||
this.reconnecting = false;
|
||
if (this.socket) {
|
||
this.socket.close(code, reason);
|
||
}
|
||
}
|
||
|
||
// 安排重连
|
||
_scheduleReconnect() {
|
||
if (this.reconnectAttempts < this.maxReconnectAttempts) {
|
||
this.reconnecting = true;
|
||
this.reconnectAttempts++;
|
||
const delay = this.reconnectInterval * Math.min(1, this.reconnectAttempts / 3); // 指数退避
|
||
|
||
console.log(`尝试重连 (${this.reconnectAttempts}/${this.maxReconnectAttempts}),${delay/1000}秒后...`);
|
||
setTimeout(() => {
|
||
console.log('正在重连...');
|
||
this.connect();
|
||
}, delay);
|
||
} else {
|
||
console.error('达到最大重连次数,停止重连');
|
||
this.reconnecting = false;
|
||
}
|
||
}
|
||
|
||
// 发送队列中的消息
|
||
_sendQueuedMessages() {
|
||
if (this.messageQueue.length > 0) {
|
||
console.log(`发送队列中的${this.messageQueue.length}条消息`);
|
||
this.messageQueue.forEach(message => {
|
||
this.socket.send(message);
|
||
});
|
||
this.messageQueue = [];
|
||
}
|
||
}
|
||
} |