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

Jak*_*nge 5 caching apollo graphql react-apollo apollo-client

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

我们有一个查询,需要一个ID数组作为参数与IDS的一个例子查询foobar看起来像这样:

query routes {
  routes(routeNames: ["foo", "bar"]) {
    items {
      name
      route
      defaults
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

缓存设置如下所示:

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 });
}
Run Code Online (Sandbox Code Playgroud)

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

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

我不确定 Apollo 是否以及如何做到这一点,因为与这里的cacheRedirect 示例相反,我们处理多个 id 而不是单个 ID。


现在,如果我们可以为每个数组项不缓存,我们可以做一个最好的事情是将IDS转换成普通缓存键,以便["foo", "bar"]["bar", "foo"]最终使用相同的缓存键,但["foo", "baz"]将使用一个不同的。

当然,理想的情况是"baz"在我们的场景中只获取缺失的项目。

Mik*_*ank 3

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

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

文档在这里:

https://www.apollographql.com/docs/react/caching/cache-interaction#readquery https://www.apollographql.com/docs/react/caching/cache-interaction#readfragment

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

https://www.apollographql.com/docs/react/data/queries/#setting-a-fetch-policy

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

https://www.apollographql.com/docs/react/api/link/introduction/