Apollo 客户端缓存没有按我的预期工作

Dam*_*nni 4 apollo graphql react-apollo apollo-client

我的问题:

我对 GraphQL 还很陌生,我正在使用 Apollo 服务器和客户端开发我的第一个全栈应用程序,这是一个简单的博客。

在客户端,我在两个不同的页面中使用相同的查询,但使用不同的变量。查询是通过 ID 或 slug 查询博客文章,具体取决于我使用的页面。所以结果是一样的,只是查询变量发生了变化。

当我在一个页面中使用查询时,我认为由于 Apollo 缓存,查询不会在第二页上运行。但事实并非如此。查询在第二个页面中再次运行,当然返回的结果与其他页面中的结果相同。

为什么 Apollo 在这种情况下不使用缓存?

这是我使用的代码:

在服务器端,我有一个非常基本的查询来从博客中获取文章,可以通过 ID 或 Slug 获取:

type Query {
  ...
  article(id: ID, slug: String): Article
  ...
}
Run Code Online (Sandbox Code Playgroud)

在客户端,如果文章已发布,我会通过 slug 查询文章;如果文章仍是草稿,我会通过 ID 查询文章。

通过 slug 进行查询:

<Query
  query={article}
  variables={{ slug }}
  fetchPolicy="cache-and-network"
>
  {({ loading, error, data }) => {
    return (
      <Article
        loading={loading}
        article={data && data.article}
      />
    );
  }}
</Query>
Run Code Online (Sandbox Code Playgroud)

通过ID查询是相同的,除了变量param使用ID:

<Query
  query={article}
  variables={{ id }}
>
  {({ loading, error, data }) => {
    return (
      <EditArticle loading={loading} article={data && data.article} />
    );
  }}
</Query>
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,两者都使用相同的 GraphQL 端点,并且结果是相同的。但没有使用缓存。

Her*_*rku 5

Apollo 假设您的解析器是纯粹的(它们没有副作用,并且在给定相同的输入/参数的情况下大多数会返回相同的结果)。这已经是很多假设了。想象一个解析器返回一个随机数或新闻网站上的最新评论。对于相同的输入,两者并不总是返回相同的结果。另一方面,Apollo 不会(而且几乎不能)对解析器的实现做出假设。虽然在您的脑海中,文章解析器的实现是显而易见的(如果存在则id返回具有该 id 的文章,如果slug存在则返回具有该 slug 的文章),这需要计算机程序进行大量猜测。

我最近回答过类似的问题。为了防止第二个查询运行,您必须实现缓存重定向。缺点是您必须保持客户端上的缓存重定向和服务器上的解析器同步。