外观设置改为单页分区;发帖草稿与板块校验优化,WS 延迟释放避开 Strict Mode 误断。
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -168,6 +168,8 @@ class RealtimeClient {
|
||||
private retryCount = 0;
|
||||
private reconnectTimer: ReturnType<typeof setTimeout> | null = null;
|
||||
private heartbeatTimer: ReturnType<typeof setInterval> | null = null;
|
||||
// Strict Mode / HMR 会瞬时卸载→重挂;延迟断开,避免握手未完成就被 close 刷控制台
|
||||
private releaseTimer: ReturnType<typeof setTimeout> | null = null;
|
||||
private readonly handlers = new Map<string, Set<RtHandler>>();
|
||||
private readonly presenceHandlers = new Set<RtHandler<RtPresenceData>>();
|
||||
private onlineIds = new Set<number>();
|
||||
@@ -177,6 +179,7 @@ class RealtimeClient {
|
||||
/** 建立连接(幂等);登录后调用 */
|
||||
connect(): void {
|
||||
if (typeof window === "undefined") return;
|
||||
this.clearReleaseTimer();
|
||||
this.wanted = true;
|
||||
if (this.state === "open" || this.state === "connecting") return;
|
||||
this.clearReconnectTimer();
|
||||
@@ -185,8 +188,21 @@ class RealtimeClient {
|
||||
document.addEventListener("visibilitychange", this.handleVisible);
|
||||
}
|
||||
|
||||
/**
|
||||
* 组件卸载时调用:短暂延迟后再真正断开。
|
||||
* 若 Strict Mode / HMR 随即重新 connect,会取消本次断开,保留握手中的连接。
|
||||
*/
|
||||
release(delayMs = 120): void {
|
||||
this.clearReleaseTimer();
|
||||
this.releaseTimer = setTimeout(() => {
|
||||
this.releaseTimer = null;
|
||||
this.disconnect();
|
||||
}, delayMs);
|
||||
}
|
||||
|
||||
/** 主动断开(登出/卸载);不再自动重连 */
|
||||
disconnect(): void {
|
||||
this.clearReleaseTimer();
|
||||
this.wanted = false;
|
||||
window.removeEventListener("online", this.handleNetworkBack);
|
||||
document.removeEventListener("visibilitychange", this.handleVisible);
|
||||
@@ -194,7 +210,15 @@ class RealtimeClient {
|
||||
this.clearHeartbeat();
|
||||
if (this.ws) {
|
||||
this.ws.onclose = null;
|
||||
this.ws.close(1000, "client logout");
|
||||
// CONNECTING 时直接 close 会触发浏览器警告;改等 open 后再关
|
||||
if (this.ws.readyState === WebSocket.CONNECTING) {
|
||||
const pending = this.ws;
|
||||
pending.onopen = () => {
|
||||
pending.close(1000, "client logout");
|
||||
};
|
||||
} else {
|
||||
this.ws.close(1000, "client logout");
|
||||
}
|
||||
this.ws = null;
|
||||
}
|
||||
this.state = "idle";
|
||||
@@ -329,6 +353,13 @@ class RealtimeClient {
|
||||
}
|
||||
}
|
||||
|
||||
private clearReleaseTimer(): void {
|
||||
if (this.releaseTimer) {
|
||||
clearTimeout(this.releaseTimer);
|
||||
this.releaseTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
private clearHeartbeat(): void {
|
||||
if (this.heartbeatTimer) {
|
||||
clearInterval(this.heartbeatTimer);
|
||||
|
||||
Reference in New Issue
Block a user