feat: 修复通知初始化问题
This commit is contained in:
@@ -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,19 +700,22 @@ export const NotificationProvider = ({ children }) => {
|
||||
}
|
||||
|
||||
// ⚡ 重连后只需重新订阅,不需要重新注册监听器
|
||||
logger.info('NotificationContext', '重新订阅事件推送');
|
||||
// 使用 setTimeout(0) 确保 socketService 内部状态已同步
|
||||
setTimeout(() => {
|
||||
logger.info('NotificationContext', '重新订阅事件推送');
|
||||
|
||||
if (socket.subscribeToEvents) {
|
||||
socket.subscribeToEvents({
|
||||
eventType: 'all',
|
||||
importance: 'all',
|
||||
onSubscribed: (data) => {
|
||||
logger.info('NotificationContext', '订阅成功', data);
|
||||
},
|
||||
});
|
||||
} else {
|
||||
logger.error('NotificationContext', 'socket.subscribeToEvents 方法不可用');
|
||||
}
|
||||
if (socket.subscribeToEvents) {
|
||||
socket.subscribeToEvents({
|
||||
eventType: 'all',
|
||||
importance: 'all',
|
||||
onSubscribed: (data) => {
|
||||
logger.info('NotificationContext', '订阅成功', data);
|
||||
},
|
||||
});
|
||||
} else {
|
||||
logger.error('NotificationContext', 'socket.subscribeToEvents 方法不可用');
|
||||
}
|
||||
}, 0);
|
||||
});
|
||||
|
||||
// ========== 监听断开连接 ==========
|
||||
|
||||
@@ -329,10 +329,18 @@ class SocketService {
|
||||
onSubscribed,
|
||||
} = options;
|
||||
|
||||
if (!this.socket || !this.connected) {
|
||||
logger.warn('socketService', 'Cannot subscribe: socket not connected');
|
||||
// 自动连接
|
||||
this.connect();
|
||||
// ⚡ 改进状态检查:同时检查 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);
|
||||
|
||||
Reference in New Issue
Block a user