fix: 错误处理

This commit is contained in:
Junhui Chen 2025-08-07 00:21:39 +08:00
parent 3469cfb332
commit ac80003c5d

View File

@ -51,19 +51,24 @@ class WebSocketManager {
* 使 token * 使 token
*/ */
public async connect() { public async connect() {
// 防止重复连接
if (this.ws && (this.status === 'connected' || this.status === 'connecting')) { if (this.ws && (this.status === 'connected' || this.status === 'connecting')) {
if (this.status === 'connected' || this.status === 'connecting') { return;
return;
}
} }
this.setStatus('connecting'); this.setStatus('connecting');
let token = ""; let token = "";
if (Platform.OS === 'web') { try {
token = localStorage.getItem('token') || ""; if (Platform.OS === 'web') {
} else { token = localStorage.getItem('token') || "";
token = await SecureStore.getItemAsync('token') || ""; } else {
token = await SecureStore.getItemAsync('token') || "";
}
} catch (error) {
console.error('获取认证 token 时出错:', error);
this.setStatus('disconnected');
return;
} }
if (!token) { if (!token) {
@ -74,9 +79,23 @@ class WebSocketManager {
console.log('WebSocket: 认证 token:', token); console.log('WebSocket: 认证 token:', token);
} }
// 检查 WebSocket 端点是否已定义
if (!WEBSOCKET_ENDPOINT) {
console.error('WebSocket: 未定义端点 URL。');
this.setStatus('disconnected');
return;
}
const url = `${WEBSOCKET_ENDPOINT}?token=${token}`; const url = `${WEBSOCKET_ENDPOINT}?token=${token}`;
console.log('WebSocket: 连接 URL:', url); console.log('WebSocket: 连接 URL:', url);
this.ws = new WebSocket(url);
try {
this.ws = new WebSocket(url);
} catch (error) {
console.error('创建 WebSocket 连接时出错:', error);
this.setStatus('disconnected');
return;
}
this.ws.onopen = () => { this.ws.onopen = () => {
console.log('WebSocket connected'); console.log('WebSocket connected');
@ -87,12 +106,24 @@ class WebSocketManager {
this.ws.onmessage = (event) => { this.ws.onmessage = (event) => {
try { try {
// 检查事件数据是否存在
if (!event.data) {
console.warn('WebSocket received empty message');
return;
}
const message: WsMessage = JSON.parse(event.data); const message: WsMessage = JSON.parse(event.data);
// console.log('WebSocket received message:', message) // console.log('WebSocket received message:', message)
// 根据消息类型分发 // 根据消息类型分发
const eventListeners = this.messageListeners.get(message.type); const eventListeners = this.messageListeners.get(message.type);
if (eventListeners) { if (eventListeners) {
eventListeners.forEach(callback => callback(message)); eventListeners.forEach(callback => {
try {
callback(message);
} catch (error) {
console.error(`处理消息类型 ${message.type} 时出错:`, error);
}
});
} }
// 可以在这里处理通用的消息,比如 Pong // 可以在这里处理通用的消息,比如 Pong
if (message.type === 'Pong') { if (message.type === 'Pong') {
@ -104,7 +135,9 @@ class WebSocketManager {
}; };
this.ws.onerror = (error) => { this.ws.onerror = (error) => {
console.error('WebSocket 发生错误:', error); console.error('WebSocket error:', error);
this.setStatus('disconnected');
this.handleReconnect();
}; };
this.ws.onclose = () => { this.ws.onclose = () => {
@ -123,15 +156,20 @@ class WebSocketManager {
* 使退 * 使退
*/ */
private handleReconnect() { private handleReconnect() {
if (this.reconnectAttempts < this.maxReconnectAttempts) { try {
this.reconnectAttempts++; if (this.reconnectAttempts < this.maxReconnectAttempts) {
const delay = this.reconnectInterval * Math.pow(2, this.reconnectAttempts - 1); this.reconnectAttempts++;
console.log(`${delay / 1000}秒后尝试重新连接 (第 ${this.reconnectAttempts} 次)...`); const delay = this.reconnectInterval * Math.pow(2, this.reconnectAttempts - 1);
setTimeout(() => { console.log(`${delay / 1000}秒后尝试重新连接 (第 ${this.reconnectAttempts} 次)...`);
this.connect(); setTimeout(() => {
}, delay); this.connect();
} else { }, delay);
console.error('WebSocket 重连失败,已达到最大尝试次数。'); } else {
console.error('WebSocket 重连失败,已达到最大尝试次数。');
this.setStatus('disconnected');
}
} catch (error) {
console.error('处理 WebSocket 重连时出错:', error);
this.setStatus('disconnected'); this.setStatus('disconnected');
} }
} }
@ -145,7 +183,13 @@ class WebSocketManager {
console.error('WebSocket 未连接,无法发送消息。'); console.error('WebSocket 未连接,无法发送消息。');
return; return;
} }
this.ws.send(JSON.stringify(message));
try {
const messageString = JSON.stringify(message);
this.ws.send(messageString);
} catch (error) {
console.error('发送 WebSocket 消息时出错:', error);
}
} }
/** /**
@ -154,10 +198,14 @@ class WebSocketManager {
* @param callback * @param callback
*/ */
public subscribe(type: WsMessage['type'], callback: (message: WsMessage) => void) { public subscribe(type: WsMessage['type'], callback: (message: WsMessage) => void) {
if (!this.messageListeners.has(type)) { try {
this.messageListeners.set(type, new Set()); if (!this.messageListeners.has(type)) {
this.messageListeners.set(type, new Set());
}
this.messageListeners.get(type)?.add(callback);
} catch (error) {
console.error(`订阅消息类型 ${type} 时出错:`, error);
} }
this.messageListeners.get(type)?.add(callback);
} }
/** /**
@ -166,12 +214,16 @@ class WebSocketManager {
* @param callback * @param callback
*/ */
public unsubscribe(type: WsMessage['type'], callback: (message: WsMessage) => void) { public unsubscribe(type: WsMessage['type'], callback: (message: WsMessage) => void) {
const eventListeners = this.messageListeners.get(type); try {
if (eventListeners) { const eventListeners = this.messageListeners.get(type);
eventListeners.delete(callback); if (eventListeners) {
if (eventListeners.size === 0) { eventListeners.delete(callback);
this.messageListeners.delete(type); if (eventListeners.size === 0) {
this.messageListeners.delete(type);
}
} }
} catch (error) {
console.error(`取消订阅消息类型 ${type} 时出错:`, error);
} }
} }
@ -179,47 +231,82 @@ class WebSocketManager {
* WebSocket * WebSocket
*/ */
public disconnect() { public disconnect() {
this.setStatus('disconnected'); try {
if (this.ws) { this.setStatus('disconnected');
this.ws.close(); if (this.ws) {
this.ws.close();
}
} catch (error) {
console.error('断开 WebSocket 连接时出错:', error);
} finally {
this.stopPing();
} }
this.stopPing();
} }
private setStatus(status: WebSocketStatus) { private setStatus(status: WebSocketStatus) {
if (this.status !== status) { try {
this.status = status; if (this.status !== status) {
this.statusListeners.forEach(listener => listener(status)); this.status = status;
this.statusListeners.forEach(listener => {
try {
listener(status);
} catch (error) {
console.error('调用状态监听器时出错:', error);
}
});
}
} catch (error) {
console.error('设置 WebSocket 状态时出错:', error);
} }
} }
public subscribeStatus(listener: StatusListener) { public subscribeStatus(listener: StatusListener) {
this.statusListeners.add(listener); try {
// Immediately invoke with current status this.statusListeners.add(listener);
listener(this.status); // Immediately invoke with current status
try {
listener(this.status);
} catch (error) {
console.error('调用状态监听器时出错:', error);
}
} catch (error) {
console.error('订阅状态监听器时出错:', error);
}
} }
public unsubscribeStatus(listener: StatusListener) { public unsubscribeStatus(listener: StatusListener) {
this.statusListeners.delete(listener); try {
this.statusListeners.delete(listener);
} catch (error) {
console.error('取消订阅状态监听器时出错:', error);
}
} }
/** /**
* *
*/ */
private startPing() { private startPing() {
this.stopPing(); // 先停止任何可能正在运行的计时器 try {
this.pingIntervalId = setInterval(() => { this.stopPing(); // 先停止任何可能正在运行的计时器
this.send({ type: 'Ping' }); this.pingIntervalId = setInterval(() => {
}, this.pingInterval); this.send({ type: 'Ping' });
}, this.pingInterval);
} catch (error) {
console.error('启动心跳机制时出错:', error);
}
} }
/** /**
* *
*/ */
private stopPing() { private stopPing() {
if (this.pingIntervalId) { try {
clearInterval(this.pingIntervalId); if (this.pingIntervalId) {
this.pingIntervalId = null; clearInterval(this.pingIntervalId);
this.pingIntervalId = null;
}
} catch (error) {
console.error('停止心跳机制时出错:', error);
} }
} }
} }