使用 Apollo 缓存具有多个 ID 的 GraphQL 查询

Cache GraphQL query with multiple ids using Apollo

我们在 Web 应用程序中使用 apollo 客户端,并且正在寻找提高缓存使用率的方法。

我们有一个以 ID 数组作为参数的查询,带有 ID foobar 的示例查询如下所示:

query routes {
  routes(routeNames: ["foo", "bar"]) {
    items {
      name
      route
      defaults
    }
  }
}

缓存设置如下所示:

export const cacheRedirects = {
  Query: {
    routes: (_: any, args: RoutesArgs, { getCacheKey }: Resolver<'name'>): Array<CacheKey> =>
      args.routeNames.map(name => getCacheKey({ __typename: 'Route', name })),
  },
};

export const dataIdFromObject = (object: QueryResult): ?string => {
  switch (object.__typename) {
    case 'Route':
      return `${object.__typename}:${object.name}`;
    default: return defaultDataIdFromObject(object);
  }
};

export function newCache(): InMemoryCache {
  return new InMemoryCache({ dataIdFromObject, cacheRedirects });
}

现在,当我们在客户端的多个位置使用查询时,我们只想获取未通过网络缓存的 routeNames 的数据,并通过缓存检索其余数据。

所以问题归结为: 当有一个查询缓存 routeNames: ["foo", "bar"] 的结果并且稍后出现另一个查询询问 routeNames: ["bar", "baz"] 的路由时,我们很乐意从缓存中获取对应于 "bar" 的结果并发送一个查询 routeNames: ["baz"].

我不确定这是否可以以及如何使用 Apollo 完成,因为与 cacheRedirect example 相比,这里我们处理多个 ID 而不是一个。


现在,如果我们不能缓存每个数组项,那么我们可以做的下一个最好的事情就是将 id 转换为公共缓存键,以便 ["foo", "bar"]["bar", "foo"] 最终使用相同的缓存键,但 ["foo", "baz"] 会使用不同的键。

当然,理想的做法是只获取 "baz" 作为我们场景中丢失的项目。

一个想法是在进行实际查询之前检查本地缓存,并简单地从要查询的ID(routeNames)列表中删除已经在缓存中的ID(routeNames)。

要在不接触网络的情况下检查缓存,请使用 readQuery()readFragment()

文档在这里:

https://www.apollographql.com/docs/react/advanced/caching.html#readquery https://www.apollographql.com/docs/react/advanced/caching.html#readfragment

更新:或者,您也可以在查询选项中将 fetchPolicy 设置为 cache-only

https://www.apollographql.com/docs/react/api/react-apollo.html#graphql-config-options-fetchPolicy

更新 2:集成检查的好方法,因此它们 运行 对于每个查询可能是自定义客户端中间件,在调用服务器之前每个请求都会 运行。

https://www.apollographql.com/docs/react/advanced/network-layer.html#linkMiddleware