使用 Apollo 缓存具有多个 ID 的 GraphQL 查询
Cache GraphQL query with multiple ids using Apollo
我们在 Web 应用程序中使用 apollo 客户端,并且正在寻找提高缓存使用率的方法。
我们有一个以 ID 数组作为参数的查询,带有 ID foo
和 bar
的示例查询如下所示:
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
我们在 Web 应用程序中使用 apollo 客户端,并且正在寻找提高缓存使用率的方法。
我们有一个以 ID 数组作为参数的查询,带有 ID foo
和 bar
的示例查询如下所示:
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