如何映射LocalStorage重复ID并实现缓存过期自动更新
解决Angular LocalStorage缓存重复与过期问题
你当前代码的核心问题在于用数组存储缓存导致无法通过唯一key快速定位,进而产生重复项;同时未针对单个缓存项做过期清理逻辑。下面是重构后的代码,直接解决这两个问题:
重构后的完整代码
getItemById(id) { const cacheKey = `StoreService_getItemById_${id}_${this.layout.emp.id}`; return this.cacheS.getOrSetCache( cacheKey, this.http.get(`${environment.API_URL}item/getById/${id}`), 300000 ); } getOrSetCache(key: string, request: Observable<any>, msToExpire = 3600000): Observable<any> { // 从LocalStorage取出缓存仓库,默认空对象 const cacheStore = JSON.parse(localStorage.getItem('product_cache_store') || '{}'); const currentCache = cacheStore[key]; const now = Date.now(); // 检查目标缓存是否存在且未过期 if (currentCache && currentCache.exp > now) { return of(currentCache.data); } // 缓存过期/不存在,发起请求并更新缓存 return request.pipe( tap(data => { // 清理所有过期缓存(优化存储空间) Object.keys(cacheStore).forEach(cacheKey => { if (cacheStore[cacheKey].exp <= now) { delete cacheStore[cacheKey]; } }); // 存入新的缓存项,自动覆盖过期的同key缓存 cacheStore[key] = { data: data, exp: now + msToExpire }; // 写回LocalStorage localStorage.setItem('product_cache_store', JSON.stringify(cacheStore)); }) ); }
关键改动说明
解决重复ID问题
- 将缓存存储结构从数组改为键值对对象,用传入的
key(包含产品ID和员工ID)作为唯一标识,直接通过cacheStore[key]定位对应缓存项,彻底避免重复存储。 - 每次请求前先检查对应key的缓存是否有效,有效则直接返回,不会重复发起HTTP请求。
解决过期自动清理与更新问题
- 每次获取缓存时,判断当前缓存项的
exp(过期时间戳)是否大于当前时间,过期则弃用该缓存。 - 请求成功后,先遍历缓存仓库删除所有过期项,再存入新缓存数据,确保LocalStorage只保留有效缓存。
- 新缓存项会自动覆盖同key的过期缓存,下次请求时直接拿到最新数据。
额外优化
- 给缓存仓库起了明确的LocalStorage键名
product_cache_store,避免和其他业务的缓存数据混淆。 - 统一用
Date.now()获取时间戳,减少重复计算。 - 清理过期缓存的逻辑可单独抽成私有方法,让代码更整洁。
内容的提问来源于stack exchange,提问作者Leonardo Lima
相关产品推荐
相关产品推荐

