我有一系列的阿波罗查询,其工作方式如下:
- 查询可以从特定的
Website
检索子资源 - 比起传递
Website
ID作为输入参数,Apollo服务器从HTTP头或cookie中检索ID。 - 因此查询看起来像这样:
query {
currentWebsite {
id
...sub-resources
}
}
在当前网站更改之前,这种方法很有效。这是因为Apollo客户端已经在缓存中有一个网站,并且将从缓存中检索第一个(错误的)网站,而不是发出另一个HTTP请求。我相信这是因为查询不包含唯一ID,所以它将所有currentWebsite
查询视为相同。
- 更新Apollo服务器以允许接收
websiteId
作为输入参数。我测试了一下,它是有效的。不幸的是,更新API将是大量的工作。 - 将
fetchPolicy
从默认值更改为cache-and-network
。这是一个快速修复,但会产生比需要更多的HTTP请求。 - 当网站更改时,手动使部分缓存无效。这是我最不喜欢的解决方案。
- 手动从缓存中读取。如果查询不存在,使用类似
network-only
的fieldPolicy调用useQuery
。这感觉很沉重。
最终,我认为这些解决方案都不是我所需要的。我觉得必须有一种方法来提供阿波罗缓存的网站ID为每个查询,这样它就可以自己确定是否应该从缓存中检索网站或获得一个新的。我发现阿波罗缓存相当不透明,但不知道从哪里开始!
所以这里的技巧是编写一个自定义keyArgs
函数,并利用您可以拥有不传递给服务器的客户端变量的事实:
query GetWebsiteById($websiteId: String) {
currentWebsite {
id
...sub-resources
}
}
在执行查询时,将您拥有的任何头值传递给$websiteId
。然后可以在keyArgs
函数中读取该变量。
const createCache = () => new InMemoryCache({
typePolicies: {
Query: {
fields: {
currentWebsite: {
keyArgs: (_, { variables }) => {
if (variables?.websiteId == null) {
return 'currentWebsite';
} else {
return `currentWebsite:${variables.websiteId}`;
}
}
}
}
}
}
});
现在它将用自己唯一的id将每个查询存储在缓存中:currentWebsite:1
,currentWebsite:2
等。