为什么我们完全需要`cacheRedirects`?

时间:2019-11-13 20:13:14

标签: graphql apollo apollo-client apollo-cache-inmemory

我阅读了interacting with cached data上的文档,虽然我了解了cacheRedirects的工作原理,但我有点困惑为什么首先需要它。这是我问另一个问题Does the Apollo client cache nested objects in React的部分原因。

  

我们知道数据很可能已经在客户端缓存中,但是由于它是通过不同的查询请求的,因此Apollo Client不知道。

那是为什么?

为清楚起见,将示例粘贴到文档中

query ListView {
  books {
    id
    title
    abstract
  }
}

query DetailView {
  book(id: $id) {
    id
    title
    abstract
  }
}

1 个答案:

答案 0 :(得分:2)

Apollo以normalized的方式缓存接收到的数据。

如果您的ListView返回的数据如下:

{
  "data": {
    "books": [
      {
        "id": 1,
        "title" "ABC",
        "__typename": "Book"
      },
      {
        "id": 2,
        "title" "DEF",
        "__typename": "Book"
      }
    ]
  }
}

每本书将基于id__typenameBook:1Book:2等)的密钥存储在缓存中。然后,该特定的缓存键列表与books根字段关联。如果再次请求books,则Apollo将看到它已经在缓存中具有该查询,并将根据键列表重新创建结果。

如果books接受一些参数,则每组参数将被视为不同的缓存条目。 books(onSale: true)可能返回的书集与books(subject: "Computer Science")不同。每组高速缓存键分别存储。如果您先运行第一个查询,然后再运行第二个查询,则第二个将是缓存未命中,并且仍然会命中服务器。

类似地,您可以进行一个查询,该查询接受一些参数并返回一本书,例如book(id: 1)。但是,在所有这些示例中,Apollo都不“了解”参数idonSale是什么。这些参数如何与返回的结果相关联是您的业务逻辑的一部分。所有Apollo“知道”的就是给定该查询和这组参数,您将获得该特定对象或对象数组。

作为人类,我可以从命名中推断出类似book(id: 2)之类的查询会返回一本ID为2的书。但是,像Apollo这样的库无法准确地推断出该信息-它如何猜测字段的正确类型或如何返回单个对象而不是对象数组?因此,如何推断id: 2转换为“其中id = 2的书”?毕竟,实际参数可能有多种方式:book(identifier: 2)book(filter: { id: 2 })等。

因此,我们使用cacheRedirects“教导”阿波罗如何查找可能已经在缓存中的数据。这有效地复制了通常驻留在服务器上的一些业务逻辑,但有助于我们避免对服务器的额外调用。