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

Apollo v3 GraphQL如何为查询的特定字段使用concatPagination进行分页缓存?

解决Apollo Client中分页结果(嵌套数组)的缓存问题

嘿,作为GraphQL新手遇到这种缓存问题太正常了!别担心,咱们完全不用重构Schema就能搞定这个分页缓存的需求,下面一步步给你讲清楚:

为什么concatPagination()直接用不行?

concatPagination()是Apollo提供的开箱即用的分页缓存策略,但它默认是针对直接返回数组的字段设计的。而你的allJobs返回的是一个包含jobs数组和hasMoreJobs的JobSearchResults对象,所以直接套用它不会生效——它不知道该去合并对象里的哪个数组。

自定义字段策略实现嵌套数组的缓存合并

我们可以手动写一个merge函数,让Apollo知道怎么处理JobSearchResults对象里的jobs数组,同时保留hasMoreJobs的最新状态。修改你的缓存配置如下:

cache: new InMemoryCache({
  typePolicies: {
    Query: {
      fields: {
        allJobs: {
          // keyArgs:指定哪些参数会区分不同的缓存条目
          // 如果你的allJobs只有分页参数(limit、cursorId),这里设为空数组,让分页请求合并到同一个缓存
          // 如果有其他过滤参数(比如department、status),要把这些参数加进来,比如keyArgs: ['department']
          keyArgs: [],
          merge(existing, incoming, { args }) {
            // 第一次查询没有缓存,直接返回新结果
            if (!existing) return incoming;
            
            // 合并jobs数组:把新分页的jobs追加到现有缓存的jobs后面
            const mergedJobs = [...existing.jobs, ...incoming.jobs];
            
            // 返回合并后的对象,hasMoreJobs用最新的传入值(因为最后一页的hasMoreJobs会是false)
            return {
              ...incoming,
              jobs: mergedJobs,
            };
          },
        },
      },
    },
  },
}),

关键细节解释:

  • keyArgs:这个配置用来告诉Apollo哪些参数是“区分缓存的关键参数”。比如如果你的allJobs支持按部门过滤,那department参数就需要加入keyArgs,这样不同部门的分页结果会被分别缓存,不会混在一起。如果只有分页参数,空数组就够了。
  • merge函数:负责把新查询的结果和现有缓存合并。我们保留了最新的hasMoreJobs(因为每次分页请求返回的hasMoreJobs才是当前的最新状态),同时把新的jobs追加到缓存数组里。

需要重构原始Schema吗?

完全不需要!Apollo Client的typePolicies就是用来在客户端适配各种Schema结构的,不管后端返回的是数组还是嵌套对象,都能通过自定义策略实现正确的缓存。除非你有其他后端层面的需求,否则没必要改动Schema。

额外小提示

如果之后你需要更复杂的分页场景(比如跳页、刷新列表),可以考虑在Schema中给jobs数组加上@connection指令,但对于当前的无限滚动/加载更多场景,上面的自定义merge策略已经足够好用了。

内容的提问来源于stack exchange,提问作者Ioannis Georgiadis

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 05:57:30