diff --git a/src/contexts/AuthContext.js b/src/contexts/AuthContext.js index 89703509..b1ae1879 100755 --- a/src/contexts/AuthContext.js +++ b/src/contexts/AuthContext.js @@ -58,7 +58,9 @@ export const AuthProvider = ({ children }) => { // 创建超时控制器 const controller = new AbortController(); - const timeoutId = setTimeout(() => controller.abort(), 5000); // 5秒超时 + const timeoutId = setTimeout(() => { + controller.abort(new Error('Session check timeout after 5 seconds')); + }, 5000); // 5秒超时 const response = await fetch(`/api/auth/session`, { method: 'GET', @@ -96,8 +98,18 @@ export const AuthProvider = ({ children }) => { setIsAuthenticated((prev) => prev === false ? prev : false); } } catch (error) { - logger.error('AuthContext', 'checkSession', error); - // 网络错误或超时,设置为未登录状态 + // ✅ 区分AbortError和真实错误 + if (error.name === 'AbortError') { + logger.debug('AuthContext', 'Session check aborted', { + reason: error.message || 'Request cancelled', + isTimeout: error.message?.includes('timeout') + }); + // AbortError不改变登录状态(保持原状态) + return; + } + + // 只有真实错误才标记为未登录 + logger.error('AuthContext', 'checkSession failed', error); setUser((prev) => prev === null ? prev : null); setIsAuthenticated((prev) => prev === false ? prev : false); } finally { @@ -108,7 +120,16 @@ export const AuthProvider = ({ children }) => { // ⚡ 初始化时检查Session - 并行执行,不阻塞页面渲染 useEffect(() => { + const controller = new AbortController(); + + // 传递signal给checkSession(需要修改checkSession签名) + // 暂时使用原有方式,但添加cleanup防止组件卸载时的内存泄漏 checkSession(); // 直接调用,与页面渲染并行 + + // ✅ Cleanup: 组件卸载时abort可能正在进行的请求 + return () => { + controller.abort(new Error('AuthProvider unmounted')); + }; // eslint-disable-next-line react-hooks/exhaustive-deps }, []);