fix: 错误处理
This commit is contained in:
parent
3469cfb332
commit
ac80003c5d
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user