优化 ws切换的时候的时序差 导致遗留上次的消息

This commit is contained in:
mmc
2026-08-20 10:07:46 +08:00
parent be8576b887
commit f22c2bedfe
2 changed files with 33 additions and 30 deletions

4
env.js
View File

@@ -15,8 +15,8 @@ const envConfig = {
//mqtt_url: "ws://1.95.137.212:8083/mqtt",
//geoserver_url: "http://192.168.2.59:7000/geoserver"
//baseURL: 'http://1.95.137.212:8081',//http://192.168.2.56:8081
baseURL: 'http://192.168.2.34:8081',//http://192.168.2.56:8081
baseURL: 'http://1.95.137.212:8081',//http://192.168.2.56:8081
//baseURL: 'http://192.168.2.34:8081',//http://192.168.2.56:8081
//baseURL: 'https://serviceri.satabot.com',
//WS_URL: 'ws://1.95.137.212:9002/ws/',
WS_URL: 'ws://192.168.2.34:9002/ws/',

View File

@@ -61,44 +61,50 @@ class WebSocketManager {
// ==================== 连接管理 ====================
public connect(serialNumber: string, wsUrl: string): void {
console.log("创建开始");//ws://192.168.2.56:9002/ws/
// 清除之前的重连计时器
console.log("创建开始");
// 清除重连计时器
if (this.reconnectTimer) {
clearTimeout(this.reconnectTimer);
this.reconnectTimer = null;
}
if (serialNumber == null || serialNumber.trim() === "") {
console.log("serialNumber 是空/空白,停止执行");
return;
}
// 如果序列号相同且已连接,跳过
if (this.ws && this.currentSerialRef === serialNumber && this.status === 'connected') {
console.log('WebSocket already connected for this device');
return;
}
// 如果序列号不同,先关闭旧连接
if (this.ws && this.currentSerialRef !== serialNumber) {
// ========== 重点修复:关闭旧连接,并且清空旧ws的事件监听,防止旧消息回调执行 ==========
if (this.ws) {
// 解绑所有事件,阻止旧ws继续触发onmessage/onclose
this.ws.onopen = null;
this.ws.onmessage = null;
this.ws.onerror = null;
this.ws.onclose = null;
this.close();
this.ws = null;
}
this.currentSerialRef = serialNumber;
this.setStatus('connecting');
this.isManualCloseRef = false;
// 提前赋值,不要等到new WebSocket之后
this.wsSerialRef = serialNumber;
console.log('Connecting WebSocket for', serialNumber);
if (serialNumber == null || serialNumber.trim() === "") {
console.log("serialNumber 是空/空白,停止执行");
return;
}
this.ws = new WebSocket(wsUrl);
this.wsSerialRef = serialNumber;
this.ws.onopen = () => {
console.log('WebSocket Connected');
this.setStatus('connected');
const dataStr = localStorage.getItem('userInfo');
if (!dataStr) {
console.error('用户信息未找到,无法发送认证包');
@@ -109,18 +115,21 @@ class WebSocketManager {
console.log('WebSocket%', token);
console.log('WebSocket%', parse);
console.log("开始发送认证包");//ws://192.168.2.56:9002/ws/
// 发送 AUTH 认证消息
console.log("开始发送认证包");
this.send({
type: 'AUTH',
token: token,
userName: parse.username,
deviceId: serialNumber,
});
};
this.ws.onmessage = (event) => {
// 【防御二次校验】只有当前活跃serial才处理消息,旧连接残留消息直接丢弃
if (this.wsSerialRef !== this.currentSerialRef) {
console.log('丢弃过期ws消息');
return;
}
try {
const data = JSON.parse(event.data);
this.handleMessage(data);
@@ -137,7 +146,7 @@ class WebSocketManager {
const { code, reason, wasClean } = event;
console.log('[WebSocket closed]', 'code =', code, 'reason =', reason || '(no reason)', 'wasClean =', wasClean);
// 如果不是当前设备的 ws,忽略
// 不是当前设备直接忽略
if (this.wsSerialRef !== this.currentSerialRef) {
console.log('🟡 ignore old ws close');
return;
@@ -146,15 +155,13 @@ class WebSocketManager {
this.ws = null;
this.setStatus('disconnected');
// 主动关闭不重连
if (this.isManualCloseRef || !this.currentSerialRef) {
return;
}
// 5 秒后自动重连
this.reconnectTimer = setTimeout(() => {
if (this.currentSerialRef === this.wsSerialRef) {
this.connect(this.currentSerialRef, wsUrl);
this.connect(this.currentSerialRef!, wsUrl);
}
}, 5000);
};
@@ -164,21 +171,17 @@ class WebSocketManager {
public close(): void {
this.isManualCloseRef = true;
if (this.reconnectTimer) {
clearTimeout(this.reconnectTimer);
this.reconnectTimer = null;
}
if (this.ws) {
console.log('Closing WebSocket');
this.ws.close();
this.ws = null;
try {
this.ws.close(1000, 'manual close');
} catch (e) {
console.warn('ws close exception', e);
}
}
this.currentSerialRef = null;
this.wsSerialRef = null;
this.setStatus('disconnected');
}
// ==================== 消息发送 ====================