Apollo分页read与merge机制疑问:为何未触发新数据请求?
关于Apollo Client分页缓存逻辑的疑问
我正在查阅Apollo文档学习分页实现方案,文档给出了分页read函数的示例,相关代码如下:
const cache = new InMemoryCache({ typePolicies: { Query: { fields: { feed: { read(existing, { args: { offset, limit }}) { // A read function should always return undefined if existing is // undefined. Returning undefined signals that the field is // missing from the cache, which instructs Apollo Client to // fetch its value from your GraphQL server. return existing && existing.slice(offset, offset + limit); }, // The keyArgs list and merge function are the same as above. keyArgs: [], merge(existing, incoming, { args: { offset = 0 }}) { const merged = existing ? existing.slice(0) : []; for (let i = 0; i < incoming.length; ++i) { merged[offset + i] = incoming[i]; } return merged; }, }, }, }, }, });
我的疑问:假设首次执行offset=0、limit=10的查询,服务器返回10条结果经merge函数存入缓存;之后执行offset=5、limit=10的查询,按代码逻辑read函数会从现有缓存截取5-10的条目,而非获取5-15的新数据。我想知道自己忽略了什么?Apollo如何触发服务器请求获取新数据?在keyArgs设为[](结果合并到单个缓存项)的情况下,新数据如何存入缓存?
解答
1. 你忽略的核心判断:缓存是否满足查询范围
你的read函数仅检查缓存是否存在,未校验现有缓存的长度是否覆盖当前查询的完整范围。第一次查询后缓存有10条数据(索引0-9),当执行offset=5、limit=10的查询时,需要的是索引5到14的10条数据,但缓存仅包含到索引9的内容。此时read函数会返回缓存中存在的5-9这5条数据,但Apollo Client会发现返回的条目数(5条)远小于请求的limit(10条),这种不匹配会触发网络请求去获取缺失的10-14条目。
2. Apollo触发服务器请求的条件
Apollo Client发起网络请求的核心场景:
read函数返回undefined(缓存完全缺失该字段);read函数返回的数据无法满足当前查询需求(比如条目数不足limit、存在缺失的索引范围)。
在你的场景中,缓存数据量不足以覆盖请求的完整范围,因此会自动发起补充请求。
3. keyArgs: []时新数据的存入逻辑
当keyArgs设为空数组时,所有feed字段的查询结果都会合并到同一个缓存项中,新数据的存入流程:
- 先复制一份现有缓存数组(避免直接修改原缓存);
- 根据当前查询的
offset,将新返回的每条数据放到数组对应的索引位置(比如请求offset=5时,新数据的第i条会被放到merged[5+i]的位置); - 合并后的数组会替换原缓存项,逐步填充完整的分页列表(比如第一次缓存0-9,合并后变为0-14)。
即使新请求返回的部分数据(5-9)和缓存已有内容重复,merge函数也会用新返回的数据覆盖对应位置(保证缓存数据的新鲜度)。
内容的提问来源于stack exchange,提问作者Mister M
相关产品推荐
相关产品推荐

