Angular Tanstack缓存Observable未生效,触发菜单折叠问题求助
问题根源
核心问题出在两点:
getAll()里的useQuery没配置合理的缓存策略,导致每次getAllAsMap()调用时,getAll()的查询会被重新触发,新数据覆盖旧数据后重置了左侧菜单的数据源,折叠状态随之丢失。getAllAsMap()的查询逻辑依赖调用getAll()而非直接复用已有缓存,进一步导致重复请求刷新数据。
解决方案
1. 给 getAll() 配置缓存与数据保留策略
通过设置 staleTime(数据新鲜时长)和 keepPreviousData(保留旧数据),确保数据未过期时不重复请求,且更新过程中不会清空旧数据避免菜单折叠:
getAll() { console.log("GET ALL INVOKED") return this.useQuery(['orgs', 'all'], () => { console.log("?????getAll internal invoked"); return this.organizationsService.getOrganizations(); }, { staleTime: 5 * 60 * 1000, // 5分钟内视为新鲜数据,不发起新请求 cacheTime: 10 * 60 * 1000, // 缓存数据保留10分钟 keepPreviousData: true // 请求新数据时保留旧数据,避免菜单突然折叠 }).result$; }
2. 修改 getAllAsMap() 直接复用缓存数据
不再通过调用 getAll() 触发查询,而是直接从 queryClient 获取已缓存的 getAll() 数据,仅在缓存不存在时才发起请求:
getAllAsMap() { console.log("GET ALL AS MAP INVOKED") return this.useQuery(['orgs', 'all', 'map'], () => { console.log(" getAllAsMap internal invoked") // 从queryClient获取getAll的缓存数据 const cachedOrgs = this.queryClient.getQueryData(['orgs', 'all']); if (cachedOrgs) { // 直接使用缓存数据转换为Map格式 return of(cachedOrgs).pipe( mapResultData(org => this.reduceOrgs(this.flattenOrgs(org))) ); } // 缓存不存在时,调用getAll获取数据 return this.getAll().pipe( mapResultData(org => this.reduceOrgs(this.flattenOrgs(org))) ); }, { // 关联getAll的缓存key,当getAll数据更新时自动刷新当前查询 queryKeyHashFn: () => ['orgs', 'all'], staleTime: 5 * 60 * 1000 // 与getAll保持一致的新鲜时长 }).result$.pipe(filterSuccess(), mapResultData(org => org.data!)); }
额外说明
staleTime和cacheTime的值可根据业务需求调整,比如设为Infinity表示永久缓存(除非主动失效)。keepPreviousData: true是避免菜单折叠的关键,它会在新请求完成前保留旧数据,不会让菜单因数据源突然重置而状态丢失。
内容的提问来源于stack exchange,提问作者NeuralCode
相关产品推荐
相关产品推荐

