2

我阅读了有关与缓存数据交互的文档,虽然我了解其cacheRedirects工作原理,但我有点困惑为什么首先需要它。这是我问另一个问题的部分原因:Apollo 客户端是否在 React 中缓存嵌套对象

我们知道数据很可能已经在客户端缓存中,但是因为它是通过不同的查询请求的,所以 Apollo 客户端不知道这一点。

这是为什么?

为了清楚起见,复制粘贴文档中的示例:

query ListView {
  books {
    id
    title
    abstract
  }
}

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

1 回答 1

4

Apollo 以标准化方式缓存它接收到的数据。

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

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

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

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

同样,您可以有一个带有一些参数并返回一本书的查询,例如book(id: 1). 然而,在所有这些例子中,阿波罗并没有“理解”这些论点idonSale是什么。这些参数与返回结果的关系是您的业务逻辑的一部分。所有 Apollo “知道”的是,给定这个查询和这组参数,你会得到这个特定的对象或对象数组。

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

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

于 2019-11-14T00:23:23.553 回答