perf: loadWatchlist 添加 localStorage 缓存(7天有效期)
- 添加 loadWatchlistFromCache/saveWatchlistToCache 缓存工具函数 - loadWatchlist 三级缓存策略:Redux → localStorage → API - toggleWatchlist 成功后自动同步更新缓存 - 减少重复 API 请求,提升页面加载性能 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -4,6 +4,56 @@ import { eventService, stockService } from '../../services/eventService';
|
||||
import { logger } from '../../utils/logger';
|
||||
import { getApiBase } from '../../utils/apiConfig';
|
||||
|
||||
// ==================== Watchlist 缓存配置 ====================
|
||||
const WATCHLIST_CACHE_KEY = 'watchlist_cache';
|
||||
const WATCHLIST_CACHE_DURATION = 7 * 24 * 60 * 60 * 1000; // 7天
|
||||
|
||||
/**
|
||||
* 从 localStorage 读取自选股缓存
|
||||
*/
|
||||
const loadWatchlistFromCache = () => {
|
||||
try {
|
||||
const cached = localStorage.getItem(WATCHLIST_CACHE_KEY);
|
||||
if (!cached) return null;
|
||||
|
||||
const { data, timestamp } = JSON.parse(cached);
|
||||
const now = Date.now();
|
||||
|
||||
// 检查缓存是否过期(7天)
|
||||
if (now - timestamp > WATCHLIST_CACHE_DURATION) {
|
||||
localStorage.removeItem(WATCHLIST_CACHE_KEY);
|
||||
logger.debug('stockSlice', '自选股缓存已过期');
|
||||
return null;
|
||||
}
|
||||
|
||||
logger.debug('stockSlice', '自选股 localStorage 缓存命中', {
|
||||
count: data?.length || 0,
|
||||
age: Math.round((now - timestamp) / 1000 / 60) + '分钟前'
|
||||
});
|
||||
return data;
|
||||
} catch (error) {
|
||||
logger.error('stockSlice', 'loadWatchlistFromCache', error);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 保存自选股到 localStorage
|
||||
*/
|
||||
const saveWatchlistToCache = (data) => {
|
||||
try {
|
||||
localStorage.setItem(WATCHLIST_CACHE_KEY, JSON.stringify({
|
||||
data,
|
||||
timestamp: Date.now()
|
||||
}));
|
||||
logger.debug('stockSlice', '自选股已缓存到 localStorage', {
|
||||
count: data?.length || 0
|
||||
});
|
||||
} catch (error) {
|
||||
logger.error('stockSlice', 'saveWatchlistToCache', error);
|
||||
}
|
||||
};
|
||||
|
||||
// ==================== Async Thunks ====================
|
||||
|
||||
/**
|
||||
@@ -153,13 +203,28 @@ export const fetchExpectationScore = createAsyncThunk(
|
||||
|
||||
/**
|
||||
* 加载用户自选股列表(包含完整信息)
|
||||
* 缓存策略:Redux 内存缓存 → localStorage 持久缓存(7天) → API 请求
|
||||
*/
|
||||
export const loadWatchlist = createAsyncThunk(
|
||||
'stock/loadWatchlist',
|
||||
async () => {
|
||||
async (_, { getState }) => {
|
||||
logger.debug('stockSlice', 'loadWatchlist');
|
||||
|
||||
try {
|
||||
// 1. 先检查 Redux 内存缓存
|
||||
const reduxCached = getState().stock.watchlist;
|
||||
if (reduxCached && reduxCached.length > 0) {
|
||||
logger.debug('stockSlice', 'Redux watchlist 缓存命中', { count: reduxCached.length });
|
||||
return reduxCached;
|
||||
}
|
||||
|
||||
// 2. 再检查 localStorage 持久缓存(7天有效期)
|
||||
const localCached = loadWatchlistFromCache();
|
||||
if (localCached && localCached.length > 0) {
|
||||
return localCached;
|
||||
}
|
||||
|
||||
// 3. 缓存无效,调用 API
|
||||
const apiBase = getApiBase();
|
||||
const response = await fetch(`${apiBase}/api/account/watchlist`, {
|
||||
credentials: 'include'
|
||||
@@ -172,6 +237,10 @@ export const loadWatchlist = createAsyncThunk(
|
||||
stock_code: item.stock_code,
|
||||
stock_name: item.stock_name,
|
||||
}));
|
||||
|
||||
// 保存到 localStorage 缓存
|
||||
saveWatchlistToCache(watchlistData);
|
||||
|
||||
logger.debug('stockSlice', '自选股列表加载成功', {
|
||||
count: watchlistData.length
|
||||
});
|
||||
@@ -490,9 +559,10 @@ const stockSlice = createSlice({
|
||||
state.watchlist = state.watchlist.filter(item => item.stock_code !== stockCode);
|
||||
}
|
||||
})
|
||||
// fulfilled: 乐观更新模式下状态已在 pending 更新,这里无需操作
|
||||
.addCase(toggleWatchlist.fulfilled, () => {
|
||||
// 状态已在 pending 时更新
|
||||
// fulfilled: 同步更新 localStorage 缓存
|
||||
.addCase(toggleWatchlist.fulfilled, (state) => {
|
||||
// 状态已在 pending 时更新,这里同步到 localStorage
|
||||
saveWatchlistToCache(state.watchlist);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user