阿波罗客户端在应该进行网络请求时错误地读取缓存



我有一系列的阿波罗查询,其工作方式如下:

  • 查询可以从特定的Website
  • 检索子资源
  • 比起传递WebsiteID作为输入参数,Apollo服务器从HTTP头或cookie中检索ID。
  • 因此查询看起来像这样:
query {
currentWebsite {
id
...sub-resources
}
}

在当前网站更改之前,这种方法很有效。这是因为Apollo客户端已经在缓存中有一个网站,并且将从缓存中检索第一个(错误的)网站,而不是发出另一个HTTP请求。我相信这是因为查询不包含唯一ID,所以它将所有currentWebsite查询视为相同。

现在我意识到有很多方法可以解决这个问题。以下是我所知道的方法,以及它们的缺点:
  1. 更新Apollo服务器以允许接收websiteId作为输入参数。我测试了一下,它是有效的。不幸的是,更新API将是大量的工作。
  2. fetchPolicy从默认值更改为cache-and-network。这是一个快速修复,但会产生比需要更多的HTTP请求。
  3. 当网站更改时,手动使部分缓存无效。这是我最不喜欢的解决方案。
  4. 手动从缓存中读取。如果查询不存在,使用类似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等。

相关内容

最新更新