微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Apollo Client 在应该发出网络请求时错误地从缓存中读取

如何解决Apollo Client 在应该发出网络请求时错误地从缓存中读取

我有一系列 Apollo 查询,其工作方式如下:

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

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

现在我知道有很多方法可以解决这个问题。以下是我所知道的方法以及明显的缺点:

  1. 更新 Apollo 服务器以允许接收 websiteId 作为输入参数。我测试了这个并且它有效。不幸的是,更新 API 需要做很多工作。
  2. fetchPolicy认值更改为类似 cache-and-network内容。这是一个快速解决方案,但会发出比需要更多的 HTTP 请求。
  3. 在网站更改时手动使部分缓存失效。这是我最不喜欢的解决方案。
  4. 手动从缓存中读取。如果查询不存在,请使用 useQuery 之类的 fieldPolicy 调用 network-only。这感觉很沉重。

最终,我认为这些解决方案中的任何一个都不是我所需要的。我觉得必须有一种方法可以为 Apollo 缓存每个查询的网站 ID,以便它可以自行确定是应该从缓存中检索网站还是获取一个新网站。我发现 Apollo 缓存相当不透明,但不知道从哪里开始!

解决方法

所以这里的技巧是编写一个 custom keyArgs function 并利用您可以拥有不传递给服务器的客户端变量这一事实:

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:1currentWebsite:2 等。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。