You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 09:25:06