fix: 错误处理
This commit is contained in:
parent
3469cfb332
commit
ac80003c5d
@ -51,20 +51,25 @@ class WebSocketManager {
|
||||
* 会自动获取并使用存储的认证 token。
|
||||
*/
|
||||
public async connect() {
|
||||
// 防止重复连接
|
||||
if (this.ws && (this.status === 'connected' || this.status === 'connecting')) {
|
||||
if (this.status === 'connected' || this.status === 'connecting') {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.setStatus('connecting');
|
||||
|
||||
let token = "";
|
||||
try {
|
||||
if (Platform.OS === 'web') {
|
||||
token = localStorage.getItem('token') || "";
|
||||
} else {
|
||||
token = await SecureStore.getItemAsync('token') || "";
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取认证 token 时出错:', error);
|
||||
this.setStatus('disconnected');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!token) {
|
||||
console.error('WebSocket: 未找到认证 token,无法连接。');
|
||||
@ -74,9 +79,23 @@ class WebSocketManager {
|
||||
console.log('WebSocket: 认证 token:', token);
|
||||
}
|
||||
|
||||
// 检查 WebSocket 端点是否已定义
|
||||
if (!WEBSOCKET_ENDPOINT) {
|
||||
console.error('WebSocket: 未定义端点 URL。');
|
||||
this.setStatus('disconnected');
|
||||
return;
|
||||
}
|
||||
|
||||
const url = `${WEBSOCKET_ENDPOINT}?token=${token}`;
|
||||
console.log('WebSocket: 连接 URL:', url);
|
||||
|
||||
try {
|
||||
this.ws = new WebSocket(url);
|
||||
} catch (error) {
|
||||
console.error('创建 WebSocket 连接时出错:', error);
|
||||
this.setStatus('disconnected');
|
||||
return;
|
||||
}
|
||||
|
||||
this.ws.onopen = () => {
|
||||
console.log('WebSocket connected');
|
||||
@ -87,12 +106,24 @@ class WebSocketManager {
|
||||
|
||||
this.ws.onmessage = (event) => {
|
||||
try {
|
||||
// 检查事件数据是否存在
|
||||
if (!event.data) {
|
||||
console.warn('WebSocket received empty message');
|
||||
return;
|
||||
}
|
||||
|
||||
const message: WsMessage = JSON.parse(event.data);
|
||||
// console.log('WebSocket received message:', message)
|
||||
// 根据消息类型分发
|
||||
const eventListeners = this.messageListeners.get(message.type);
|
||||
if (eventListeners) {
|
||||
eventListeners.forEach(callback => callback(message));
|
||||
eventListeners.forEach(callback => {
|
||||
try {
|
||||
callback(message);
|
||||
} catch (error) {
|
||||
console.error(`处理消息类型 ${message.type} 时出错:`, error);
|
||||
}
|
||||
});
|
||||
}
|
||||
// 可以在这里处理通用的消息,比如 Pong
|
||||
if (message.type === 'Pong') {
|
||||
@ -104,7 +135,9 @@ class WebSocketManager {
|
||||
};
|
||||
|
||||
this.ws.onerror = (error) => {
|
||||
console.error('WebSocket 发生错误:', error);
|
||||
console.error('WebSocket error:', error);
|
||||
this.setStatus('disconnected');
|
||||
this.handleReconnect();
|
||||
};
|
||||
|
||||
this.ws.onclose = () => {
|
||||
@ -123,6 +156,7 @@ class WebSocketManager {
|
||||
* 处理自动重连逻辑,使用指数退避策略。
|
||||
*/
|
||||
private handleReconnect() {
|
||||
try {
|
||||
if (this.reconnectAttempts < this.maxReconnectAttempts) {
|
||||
this.reconnectAttempts++;
|
||||
const delay = this.reconnectInterval * Math.pow(2, this.reconnectAttempts - 1);
|
||||
@ -134,6 +168,10 @@ class WebSocketManager {
|
||||
console.error('WebSocket 重连失败,已达到最大尝试次数。');
|
||||
this.setStatus('disconnected');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('处理 WebSocket 重连时出错:', error);
|
||||
this.setStatus('disconnected');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -145,7 +183,13 @@ class WebSocketManager {
|
||||
console.error('WebSocket 未连接,无法发送消息。');
|
||||
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 收到消息时的回调函数。
|
||||
*/
|
||||
public subscribe(type: WsMessage['type'], callback: (message: WsMessage) => void) {
|
||||
try {
|
||||
if (!this.messageListeners.has(type)) {
|
||||
this.messageListeners.set(type, new Set());
|
||||
}
|
||||
this.messageListeners.get(type)?.add(callback);
|
||||
} catch (error) {
|
||||
console.error(`订阅消息类型 ${type} 时出错:`, error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -166,6 +214,7 @@ class WebSocketManager {
|
||||
* @param callback 要移除的回调函数。
|
||||
*/
|
||||
public unsubscribe(type: WsMessage['type'], callback: (message: WsMessage) => void) {
|
||||
try {
|
||||
const eventListeners = this.messageListeners.get(type);
|
||||
if (eventListeners) {
|
||||
eventListeners.delete(callback);
|
||||
@ -173,54 +222,92 @@ class WebSocketManager {
|
||||
this.messageListeners.delete(type);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`取消订阅消息类型 ${type} 时出错:`, error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 手动断开 WebSocket 连接。
|
||||
*/
|
||||
public disconnect() {
|
||||
try {
|
||||
this.setStatus('disconnected');
|
||||
if (this.ws) {
|
||||
this.ws.close();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('断开 WebSocket 连接时出错:', error);
|
||||
} finally {
|
||||
this.stopPing();
|
||||
}
|
||||
}
|
||||
|
||||
private setStatus(status: WebSocketStatus) {
|
||||
try {
|
||||
if (this.status !== status) {
|
||||
this.status = status;
|
||||
this.statusListeners.forEach(listener => listener(status));
|
||||
this.statusListeners.forEach(listener => {
|
||||
try {
|
||||
listener(status);
|
||||
} catch (error) {
|
||||
console.error('调用状态监听器时出错:', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('设置 WebSocket 状态时出错:', error);
|
||||
}
|
||||
}
|
||||
|
||||
public subscribeStatus(listener: StatusListener) {
|
||||
try {
|
||||
this.statusListeners.add(listener);
|
||||
// Immediately invoke with current status
|
||||
try {
|
||||
listener(this.status);
|
||||
} catch (error) {
|
||||
console.error('调用状态监听器时出错:', error);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('订阅状态监听器时出错:', error);
|
||||
}
|
||||
}
|
||||
|
||||
public unsubscribeStatus(listener: StatusListener) {
|
||||
try {
|
||||
this.statusListeners.delete(listener);
|
||||
} catch (error) {
|
||||
console.error('取消订阅状态监听器时出错:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动心跳机制。
|
||||
*/
|
||||
private startPing() {
|
||||
try {
|
||||
this.stopPing(); // 先停止任何可能正在运行的计时器
|
||||
this.pingIntervalId = setInterval(() => {
|
||||
this.send({ type: 'Ping' });
|
||||
}, this.pingInterval);
|
||||
} catch (error) {
|
||||
console.error('启动心跳机制时出错:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止心跳机制。
|
||||
*/
|
||||
private stopPing() {
|
||||
try {
|
||||
if (this.pingIntervalId) {
|
||||
clearInterval(this.pingIntervalId);
|
||||
this.pingIntervalId = null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('停止心跳机制时出错:', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user