181 lines
5.0 KiB
JavaScript
181 lines
5.0 KiB
JavaScript
export class WebSocketManager {
|
|
constructor(url) {
|
|
this.url = url;
|
|
this.socket = null;
|
|
this.isConnected = false;
|
|
this.reconnectAttempts = 0;
|
|
this.maxReconnectAttempts = 5;
|
|
this.reconnectDelay = 1000;
|
|
this.messageHandlers = [];
|
|
this.pingInterval = null;
|
|
}
|
|
|
|
connect() {
|
|
if (this.isConnected) return;
|
|
|
|
console.log('正在连接WebSocket...');
|
|
this.socket = uni.connectSocket({
|
|
url: this.url,
|
|
success: () => {
|
|
console.log('WebSocket连接成功');
|
|
},
|
|
fail: (err) => {
|
|
console.error('WebSocket连接失败:', err);
|
|
this.handleReconnect();
|
|
}
|
|
});
|
|
|
|
this.socket.onOpen(() => {
|
|
console.log('WebSocket连接已打开');
|
|
this.isConnected = true;
|
|
this.reconnectAttempts = 0;
|
|
|
|
// 开始心跳检测
|
|
this.startHeartbeat();
|
|
|
|
// 绑定当前用户
|
|
const userId = uni.getStorageSync('userId');
|
|
if (userId) {
|
|
this.bindUser(userId);
|
|
}
|
|
});
|
|
|
|
this.socket.onMessage((res) => {
|
|
try {
|
|
const data = JSON.parse(res.data);
|
|
console.log('收到消息:', data);
|
|
this.handleMessage(data);
|
|
} catch (e) {
|
|
console.error('解析消息失败:', e);
|
|
}
|
|
});
|
|
|
|
this.socket.onClose((res) => {
|
|
console.log('WebSocket连接关闭:', res);
|
|
this.isConnected = false;
|
|
this.stopHeartbeat();
|
|
this.handleReconnect();
|
|
});
|
|
|
|
this.socket.onError((err) => {
|
|
console.error('WebSocket错误:', err);
|
|
});
|
|
}
|
|
|
|
bindUser(userId) {
|
|
this.send({
|
|
type: 'bind',
|
|
userId: userId
|
|
});
|
|
}
|
|
|
|
send(message) {
|
|
if (!this.isConnected) {
|
|
console.error('WebSocket未连接');
|
|
return false;
|
|
}
|
|
|
|
try {
|
|
const messageStr = JSON.stringify(message);
|
|
this.socket.send({
|
|
data: messageStr,
|
|
success: () => {
|
|
console.log('消息发送成功:', message);
|
|
},
|
|
fail: (err) => {
|
|
console.error('消息发送失败:', err);
|
|
}
|
|
});
|
|
return true;
|
|
} catch (err) {
|
|
console.error('发送消息出错:', err);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
addMessageHandler(handler) {
|
|
this.messageHandlers.push(handler);
|
|
}
|
|
|
|
removeMessageHandler(handler) {
|
|
const index = this.messageHandlers.indexOf(handler);
|
|
if (index !== -1) {
|
|
this.messageHandlers.splice(index, 1);
|
|
}
|
|
}
|
|
|
|
handleMessage(data) {
|
|
// 如果对象中有clientId则给websocket发送
|
|
if (data.clientId) {
|
|
const userId = uni.getStorageSync('user_id'); // 实际项目中从存储获取
|
|
const bindMessage = {
|
|
request_type: 'bind',
|
|
user_type: 'user',
|
|
sender_user_id: `user-${userId}`,
|
|
};
|
|
this.send(bindMessage);
|
|
}
|
|
|
|
// 处理聊天消息
|
|
if (data.message_type !== undefined) {
|
|
// 将消息转发给聊天管理器
|
|
this.messageHandlers.forEach(handler => {
|
|
try {
|
|
handler(data);
|
|
} catch (e) {
|
|
console.error('消息处理出错:', e);
|
|
}
|
|
});
|
|
} else {
|
|
// 其他消息处理
|
|
this.messageHandlers.forEach(handler => {
|
|
try {
|
|
handler(data);
|
|
} catch (e) {
|
|
console.error('消息处理出错:', e);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
startHeartbeat() {
|
|
this.pingInterval = setInterval(() => {
|
|
if (this.isConnected) {
|
|
this.send({type: 'ping'});
|
|
}
|
|
}, 300000);
|
|
}
|
|
|
|
stopHeartbeat() {
|
|
if (this.pingInterval) {
|
|
clearInterval(this.pingInterval);
|
|
this.pingInterval = null;
|
|
}
|
|
}
|
|
|
|
handleReconnect() {
|
|
if (this.reconnectAttempts >= this.maxReconnectAttempts) {
|
|
console.log('已达到最大重连次数');
|
|
return;
|
|
}
|
|
|
|
setTimeout(() => {
|
|
this.reconnectAttempts++;
|
|
this.reconnectDelay = Math.min(this.reconnectDelay * 2, 30000);
|
|
console.log(`尝试重连 (${this.reconnectAttempts}/${this.maxReconnectAttempts})`);
|
|
this.connect();
|
|
}, this.reconnectDelay);
|
|
}
|
|
|
|
disconnect() {
|
|
if (this.socket) {
|
|
this.socket.close();
|
|
this.socket = null;
|
|
}
|
|
this.isConnected = false;
|
|
this.stopHeartbeat();
|
|
}
|
|
}
|
|
|
|
// 全局WebSocket实例
|
|
export const webSocketManager = new WebSocketManager('ws://127.0.0.1:12080/ws'); |