feat: 修复通知初始化问题
This commit is contained in:
@@ -27,6 +27,9 @@ const CONNECTION_STATUS = {
|
|||||||
RECONNECTED: 'reconnected', // 重连成功(显示2秒后自动变回 CONNECTED)
|
RECONNECTED: 'reconnected', // 重连成功(显示2秒后自动变回 CONNECTED)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ⚡ 模块级变量:防止 React Strict Mode 导致的重复初始化
|
||||||
|
let socketInitialized = false;
|
||||||
|
|
||||||
// 创建通知上下文
|
// 创建通知上下文
|
||||||
const NotificationContext = createContext();
|
const NotificationContext = createContext();
|
||||||
|
|
||||||
@@ -651,14 +654,21 @@ export const NotificationProvider = ({ children }) => {
|
|||||||
|
|
||||||
// ========== 连接到 Socket 服务(⚡ 异步初始化,不阻塞首屏) ==========
|
// ========== 连接到 Socket 服务(⚡ 异步初始化,不阻塞首屏) ==========
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
// ⚡ 防止 React Strict Mode 导致的重复初始化
|
||||||
|
if (socketInitialized) {
|
||||||
|
logger.debug('NotificationContext', 'Socket 已初始化,跳过重复执行(Strict Mode 保护)');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let cleanupCalled = false;
|
let cleanupCalled = false;
|
||||||
let idleCallbackId;
|
let idleCallbackId;
|
||||||
let timeoutId;
|
let timeoutId;
|
||||||
|
|
||||||
// ⚡ Socket 初始化函数(将在浏览器空闲时执行)
|
// ⚡ Socket 初始化函数(将在浏览器空闲时执行)
|
||||||
const initSocketConnection = () => {
|
const initSocketConnection = () => {
|
||||||
if (cleanupCalled) return; // 防止组件卸载后执行
|
if (cleanupCalled || socketInitialized) return; // 防止组件卸载后执行或重复初始化
|
||||||
|
|
||||||
|
socketInitialized = true; // 标记已初始化
|
||||||
logger.info('NotificationContext', '初始化 Socket 连接(异步执行,不阻塞首屏)');
|
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) {
|
if (socket.subscribeToEvents) {
|
||||||
socket.subscribeToEvents({
|
socket.subscribeToEvents({
|
||||||
eventType: 'all',
|
eventType: 'all',
|
||||||
importance: 'all',
|
importance: 'all',
|
||||||
onSubscribed: (data) => {
|
onSubscribed: (data) => {
|
||||||
logger.info('NotificationContext', '订阅成功', data);
|
logger.info('NotificationContext', '订阅成功', data);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
logger.error('NotificationContext', 'socket.subscribeToEvents 方法不可用');
|
logger.error('NotificationContext', 'socket.subscribeToEvents 方法不可用');
|
||||||
}
|
}
|
||||||
|
}, 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
// ========== 监听断开连接 ==========
|
// ========== 监听断开连接 ==========
|
||||||
|
|||||||
@@ -329,10 +329,18 @@ class SocketService {
|
|||||||
onSubscribed,
|
onSubscribed,
|
||||||
} = options;
|
} = options;
|
||||||
|
|
||||||
if (!this.socket || !this.connected) {
|
// ⚡ 改进状态检查:同时检查 this.connected 和 socket.connected
|
||||||
logger.warn('socketService', 'Cannot subscribe: socket not connected');
|
// 解决 connect 回调中 this.connected 尚未更新的竞争条件
|
||||||
// 自动连接
|
const isReady = this.socket && (this.socket.connected || this.connected);
|
||||||
this.connect();
|
|
||||||
|
if (!isReady) {
|
||||||
|
logger.debug('socketService', 'Socket 尚未就绪,等待连接后订阅');
|
||||||
|
|
||||||
|
if (!this.socket) {
|
||||||
|
// 自动连接
|
||||||
|
this.connect();
|
||||||
|
}
|
||||||
|
|
||||||
// 等待连接成功后再订阅
|
// 等待连接成功后再订阅
|
||||||
this.socket.once('connect', () => {
|
this.socket.once('connect', () => {
|
||||||
this._doSubscribe(eventType, importance, onNewEvent, onSubscribed);
|
this._doSubscribe(eventType, importance, onNewEvent, onSubscribed);
|
||||||
|
|||||||
Reference in New Issue
Block a user