React SPA定时调用API刷新AccessToken的最优实现方案咨询
React SPA 固定间隔刷新AccessToken的最优方案
核心问题分析
你之前的实现会在页面刷新/路由切换后重置定时器,导致调用间隔被打乱。要实现登录后启动、不受页面刷新/路由跳转影响的固定5分钟调用,关键是要持久化记录上次调用时间,同时封装独立的定时器管理逻辑。
具体实现方案
1. 封装刷新Token的核心函数
const refreshAccessToken = async () => { try { const response = await fetch('/api/refresh-token', { method: 'POST', credentials: 'include' // 需携带Cookie时启用 }); const data = await response.json(); // 更新本地存储的Token信息 localStorage.setItem('accessToken', data.accessToken); // 记录本次刷新的时间戳 localStorage.setItem('lastRefreshTime', Date.now().toString()); } catch (error) { console.error('Token刷新失败:', error); // 失败处理:比如清除本地Token并跳转登录页 localStorage.removeItem('accessToken'); window.location.href = '/login'; } };
2. 封装定时器管理的自定义Hook
import { useEffect, useRef } from 'react'; const useTokenRefreshTimer = (isLoggedIn) => { const intervalRef = useRef(null); const REFRESH_INTERVAL = 5 * 60 * 1000; // 5分钟间隔 useEffect(() => { // 未登录时清除定时器并清理记录 if (!isLoggedIn) { if (intervalRef.current) { clearInterval(intervalRef.current); intervalRef.current = null; } localStorage.removeItem('lastRefreshTime'); return; } // 计算首次调用的延迟时间:基于上次刷新时间补全剩余间隔 const lastRefreshTime = parseInt(localStorage.getItem('lastRefreshTime') || Date.now().toString(), 10); const now = Date.now(); const delay = Math.max(0, REFRESH_INTERVAL - (now - lastRefreshTime)); // 启动定时器逻辑 const startTimer = () => { // 先延迟执行首次刷新,再设置固定间隔 const timeoutId = setTimeout(() => { refreshAccessToken(); intervalRef.current = setInterval(refreshAccessToken, REFRESH_INTERVAL); }, delay); return () => clearTimeout(timeoutId); }; const clearTimer = startTimer(); // 组件卸载时清理定时器 return () => { clearTimer(); if (intervalRef.current) { clearInterval(intervalRef.current); intervalRef.current = null; } }; }, [isLoggedIn]); }; export default useTokenRefreshTimer;
3. 在根组件中使用Hook
import useTokenRefreshTimer from './hooks/useTokenRefreshTimer'; function App() { // 从本地存储判断登录状态(也可结合Redux/Zustand等状态管理) const isLoggedIn = !!localStorage.getItem('accessToken'); // 挂载定时器逻辑 useTokenRefreshTimer(isLoggedIn); return ( <div className="App"> {/* 你的路由与页面内容 */} </div> ); } export default App;
关键细节说明
- 持久化时间记录:通过
localStorage存储上次刷新时间,页面刷新后能基于该时间计算剩余延迟,保证调用间隔严格为5分钟。 - 登录状态联动:登录成功后自动启动定时器,退出登录时自动清除定时器与时间记录。
- 异常处理:刷新失败时自动清理本地Token并跳转登录页,避免无效循环调用。
内容的提问来源于stack exchange,提问作者asallan3
相关产品推荐
相关产品推荐

