Files
QCN_rider/.svn/pristine/72/72fc59a45126280b0428a576850a52c893f09b6e.svn-base
2026-02-12 12:19:20 +08:00

139 lines
5.2 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// src/Service/Im/WebSocket.ts
import { EventHandler } from '@/Service/Comm/EventHandler';
import { Service, ImConnectService } from '@/Service/Im/ImConnectService';
class WebSocketManager {
private socketTask: UniApp.SocketTask | null = null;
private heartbeatInterval: ReturnType<typeof setInterval> | null = null;
private readonly heartbeat: number = 30000; // 建议心跳30秒
private isConnecting: boolean = false; // 连接状态锁
private isUserClose: boolean = false; // 是否是用户主动关闭
public ConnectSocketInit(): void {
if (this.isConnecting || this.socketTask) {
console.warn('WebSocket 正在连接或已连接,请勿重复调用。');
return;
}
this.isConnecting = true;
this.isUserClose = false;
ImConnectService.GetConnect().then((res: any) => {
if (res.code !== 0) {
this.isConnecting = false;
// Service.Msg('获取连接地址失败');
return;
}
Service.SetUserClientId(res.data.websocketId);
this.socketTask = uni.connectSocket({
url: res.data.server,
header: { 'content-type': 'application/json' },
// 推荐在小程序端开启 BSON
// #ifdef MP-WEIXIN
// protocols: ['bson'],
// #endif
success: () => {}, // success回调仅表示任务创建成功
});
// ✅ 绑定事件监听 (在 onOpen 外部)
this.socketTask.onOpen(() => {
console.log('==============WebSocket连接正常=============');
this.isConnecting = false;
this.startHeartbeat();
EventHandler.ConnectBus();
});
this.socketTask.onMessage((data: any) => {
console.log('接收到消息');
EventHandler.Events(data);
});
this.socketTask.onClose((e: any) => {
console.log('========WebSocket连接已被关闭========', e);
this.isConnecting = false;
this.stopHeartbeat();
this.socketTask = null; // 清理实例
// 如果不是用户主动关闭,则触发重连
if (!this.isUserClose) {
this.reconnect();
}
});
this.socketTask.onError((err: any) => {
console.error('========WebSocket连接发生错误========', err);
this.isConnecting = false;
// 错误发生时,通常也会触发 onClose由 onClose 统一处理重连
});
}).catch(err => {
this.isConnecting = false;
console.error('GetConnect API 请求失败:', err);
});
}
private startHeartbeat(): void {
this.stopHeartbeat(); // 先停止旧的,确保只有一个
const heartbeatData = JSON.stringify({ code: 'Heart', method: 'Heart' });
this.heartbeatInterval = setInterval(() => {
console.log('======发送心跳检测======');
this.send(heartbeatData);
}, this.heartbeat);
}
private stopHeartbeat(): void {
if (this.heartbeatInterval) {
clearInterval(this.heartbeatInterval);
this.heartbeatInterval = null;
}
}
// 重新连接 (带延迟和重试次数)
public reconnect(): void {
console.log('准备在3秒后尝试重连...');
setTimeout(() => {
console.log('正在尝试重连...');
this.ConnectSocketInit();
// 在您的 EventHandler 或全局事件总线中可以增加重试次数限制
uni.$emit('ImReconnecting');
}, 3000); // 延迟3秒重连避免频繁请求
}
public CloseSocket(reason: string = 'user close'): void {
if (!this.socketTask) return;
this.isUserClose = true;
this.stopHeartbeat(); // ✅ 立即停止心跳
this.socketTask.close({
code: 1000,
reason: reason,
success: () => { // ✅ 使用箭头函数
console.log('===============关闭 WebSocket 成功===================');
},
fail: (err) => { // ✅ 使用箭头函数
console.log('===================关闭 WebSocket 失败=====================', err);
}
});
}
public send(value: any): void {
if (this.socketTask && this.socketTask.readyState === 1) { // 检查连接状态
this.socketTask.send({
data: value,
success: () => {}, // ✅ 使用箭头函数
fail: (err) => { // ✅ 使用箭头函数
console.error('发送消息失败:', err);
// 发送失败通常意味着连接已断开onClose会处理重连
}
});
} else {
console.error('WebSocket 未连接,无法发送消息。');
// 可以考虑将消息放入一个队列,等重连成功后再发送
}
}
}
// 导出单例模式
export const WebSocket = new WebSocketManager();