feat: 修复通知初始化问题

This commit is contained in:
zdl
2025-11-26 10:55:38 +08:00
parent 1090a2fc67
commit 2fcc341213
2 changed files with 38 additions and 17 deletions

View File

@@ -27,6 +27,9 @@ const CONNECTION_STATUS = {
RECONNECTED: 'reconnected', // 重连成功显示2秒后自动变回 CONNECTED
};
// ⚡ 模块级变量:防止 React Strict Mode 导致的重复初始化
let socketInitialized = false;
// 创建通知上下文
const NotificationContext = createContext();
@@ -651,14 +654,21 @@ export const NotificationProvider = ({ children }) => {
// ========== 连接到 Socket 服务(⚡ 异步初始化,不阻塞首屏) ==========
useEffect(() => {
// ⚡ 防止 React Strict Mode 导致的重复初始化
if (socketInitialized) {
logger.debug('NotificationContext', 'Socket 已初始化跳过重复执行Strict Mode 保护)');
return;
}
let cleanupCalled = false;
let idleCallbackId;
let timeoutId;
// ⚡ Socket 初始化函数(将在浏览器空闲时执行)
const initSocketConnection = () => {
if (cleanupCalled) return; // 防止组件卸载后执行
if (cleanupCalled || socketInitialized) return; // 防止组件卸载后执行或重复初始化
socketInitialized = true; // 标记已初始化
logger.info('NotificationContext', '初始化 Socket 连接(异步执行,不阻塞首屏)');
// ========== 监听连接成功(首次连接 + 重连) ==========
@@ -690,6 +700,8 @@ export const NotificationProvider = ({ children }) => {
}
// ⚡ 重连后只需重新订阅,不需要重新注册监听器
// 使用 setTimeout(0) 确保 socketService 内部状态已同步
setTimeout(() => {
logger.info('NotificationContext', '重新订阅事件推送');
if (socket.subscribeToEvents) {
@@ -703,6 +715,7 @@ export const NotificationProvider = ({ children }) => {
} else {
logger.error('NotificationContext', 'socket.subscribeToEvents 方法不可用');
}
}, 0);
});
// ========== 监听断开连接 ==========

View File

@@ -329,10 +329,18 @@ class SocketService {
onSubscribed,
} = options;
if (!this.socket || !this.connected) {
logger.warn('socketService', 'Cannot subscribe: socket not connected');
// ⚡ 改进状态检查:同时检查 this.connected 和 socket.connected
// 解决 connect 回调中 this.connected 尚未更新的竞争条件
const isReady = this.socket && (this.socket.connected || this.connected);
if (!isReady) {
logger.debug('socketService', 'Socket 尚未就绪,等待连接后订阅');
if (!this.socket) {
// 自动连接
this.connect();
}
// 等待连接成功后再订阅
this.socket.once('connect', () => {
this._doSubscribe(eventType, importance, onNewEvent, onSubscribed);