GraphQL Apollo分页与type policies配置 翻页结果追加缓存问题
配置错误点
- 参数名拼写不一致:请求参数里的字段是
includePartialMatch,但你在keyArgs中写的是includePartialMatches,多了末尾的s,直接导致参数匹配失效。 - keyArgs逻辑遗漏:你需要让
page、itemsToShow这两个分页参数不参与缓存key的生成,当前配置没有明确排除这两个字段,导致不同page的请求被判定为独立的缓存条目。 - merge函数逻辑不完善:默认merge函数可接收第三个上下文参数
args,你未接收该参数无法做分页相关的精细控制,同时现有合并逻辑未处理重复条目、分页元数据覆盖的边界情况。
修正后可用配置
const typePolicy = { // 仅用search下除page、itemsToShow之外的字段生成缓存key keyArgs: [ "search", [ "identifier", "searchTerm", "includePartialMatch", // 修正拼写与请求参数一致 "filters", "orderBy", "facets", ], ], merge(existing, incoming, { args }) { // 首次请求无现有缓存直接返回新数据 if (!existing) return { ...incoming }; // 合并条目,基于id去重避免重复数据 const itemMap = new Map(existing.items.map(item => [item.id, item])); incoming.items.forEach(item => itemMap.set(item.id, item)); return { ...existing, ...incoming, items: Array.from(itemMap.values()), // 总数等元数据优先用最新接口返回的值 total: incoming.total ?? existing.total }; }, // 可选配置:如果需要按请求参数返回对应页的数据,加上read函数,不需要可直接删除 read(existing, { args }) { if (!existing) return undefined; const page = args?.search?.page ?? 1; const pageSize = args?.search?.itemsToShow ?? 10; const startIndex = (page - 1) * pageSize; return { ...existing, items: existing.items.slice(startIndex, startIndex + pageSize) }; } };
注意事项
- 如果搜索返回的条目没有全局唯一的
id字段,需要在InMemoryCache配置中给对应返回类型添加keyFields,避免缓存条目识别错误。 - 如果不需要前端按分页参数切片返回对应页数据,直接删除
read函数即可,Apollo会默认返回全部合并后的条目。
内容的提问来源于stack exchange,提问作者r3plica
相关产品推荐
相关产品推荐

