发布于 2026-01-06 5 阅读
0

如何使用 Apollo GraphQL Cache 嗨翻全场 🎉🎈

如何使用 Apollo GraphQL Cache 嗨翻全场 🎉🎈

大家好,我是 apollo-cache-inmemory,也就是 Apollo Cache。我是 Apollo Client 中缓存的默认实现。那么,让我来解释一下我们为什么在这里!

我会随时帮助你访问和操作缓存。你执行了数据变更吗?别担心!我可以帮你更新缓存。对了,Redux 的开发者确实很棒,但你可能不再需要用它存储数据了🤷‍♂。让我来……

呃……谢谢 Apollo Cache 的介绍,不过我想我会继续做下去。

好吧,我第一次尝试 Apollo Cache 的时候,感觉完全摸不着头脑。它的用例太多了,我肯定会迷失方向。再加上其他一些__typename乱七八糟的东西,就更让人困惑了。所以我决定好好研究一下 Apollo Cache。事情是这样的:
首先,你得邀请 Apollo Cache 加入你的团队:

npm install apollo-cache-inmemory --save
Enter fullscreen mode Exit fullscreen mode

现在,Apollo Cache它就能立刻引爆全场。只需将其引入 Apollo Client(Apollo Client 对缓存情有独钟),然后就大功告成了!

const cache = new InMemoryCache();

const client = new ApolloClient({
  link: new HttpLink(),
  cache
});
Enter fullscreen mode Exit fullscreen mode

但我们希望它能做更多的事情。所以,请让它理解你们的党规,以便它能按照你们的意愿运行。比如这样code of conduct?我们会在构造函数中提供行为准则。顺便说一句,这完全是可选的。好了,开始吧!

行为守则:

替代文字

addTypename:一个布尔值,用于指定是否将 __typename 添加到文档中。(默认为 true)。稍后会详细介绍。

`dataIdFromObject`:缓存会在将数据保存到 store 之前对其进行规范化处理。这是一个接收数据对象并返回唯一 ID 的函数。稍后会详细介绍它的用法。

fragmentMatcher: Apollo Cache 默认使用启发式片段匹配器。如果您计划在联合体和接口上使用片段,则需要告知 Apollo Cache 此项设置,这有点奇怪。

cacheRedirects:有时,我们会请求 Apollo Cache 存储中已存在的数据,但该数据位于不同的资源键下。通过 cacheRedirects,我们可以告诉 Apollo Cache 在哪里查找已存在的数据。


替代文字

Apollo Cache 在派对上迅速走红。所有派对参与者(你可以把他们想象成组件)都在与缓存进行交互。我们玩的是 React 和 Act 🧐,缓存里存储着所有我们可以操作的事件以及每个团队的得分。而且我必须说,它的表现非常出色。Apollo Cache 通过以下三点实现了数据的快速存储和检索——

  1. 将数据拆分成单个对象
  2. 为每个对象创建一个唯一标识符
  3. 将数据存储在扁平化的数据结构中

它使用了行为准则中的`addTypename``dataIdFromObject`函数来实现这一点。通常,缓存会使用数据中找到的 `id`id` id` 字段来创建唯一标识符。如果数据中没有提供 `id`,它将使用 `id` 字段作为键。`dataIdFromObject`函数指示缓存使用数据中的特定字段作为唯一标识符,以便之后在与 Apollo 缓存的任何交互(查询)中引用它。_id__typename__typename

我知道这有点让人困惑。所以,我们来详细讨论一下:
首先,缓存是如何记住所有信息的?简单来说,Apollo 缓存会记住你与它的交互方式。缓存将此称为查询路径

query {
    Events (category = 'happy') { 
        name
    }
}
Enter fullscreen mode Exit fullscreen mode

对于上述查询,缓存将创建如下查询路径:RootQuery -> Events(category = 'happy') -> name。它假定每个查询路径都指向一个唯一的资源。因此,下次有人向缓存提出相同的查询时,它就能立即给出答案。例如,一位访客向 Apollo 缓存询问了团队的得分以及“happy”类别下的活动列表。

query {
    Score(team = 'A') {
        points
    }
    Events (category = 'happy') { 
        name
    }
}
Enter fullscreen mode Exit fullscreen mode

缓存已经知道事件列表,因为之前有人已经查询过。所以它立即做出了响应。真快!

缓存会尽力记住信息。但有时,查询路径不够清晰。例如,以下是其他两位访客提出的问题:

访客A:嗨,Apollo Cache。你能告诉我“跳舞”类别下的活动吗?
访客B:Cache,你能告诉我第二类活动吗?(这里类别是通过ID来引用的)

现在,id = 2(或第二类)的事件实际上属于“跳舞”类别。缓存是如何看待这些请求的呢?

// 1st Request
query {
    Event (category = 'dancing') { 
        name
    }
}
// 2nd Request
query {
    Event (id = 2) { 
        name
    }
}
Enter fullscreen mode Exit fullscreen mode

这里,缓存并不知道这两个请求指向的是同一个结果。正常情况下,缓存会获取该数据并将其保存两次。此时,缓存能够通过dataIdFromObject规则来判断这些请求的真正含义。
这是怎么做到的呢?这需要我们稍加引导。因此,dataIdFromObject我们需要为任何需要查询的对象指定一个唯一标识符。这里,我们需要注意不要使用原始 ID(SQL 主键)作为唯一标识符,因为 id = 5 既可以代表一个事件,也可以代表一个访客。我们需要结合使用 `id = 5` 和 `id = 5`。因此,__typename像 `id = 5` 这样的标识符Event:5仅代表 id = 5 的事件数据,而Guest:5`id = 5` 仅代表 id = 5 的访客数据。

替代文字

如果舞蹈类别中的活动名称从“bachata”更改为“salsa”,则以上两个查询的答案都会更新。简单又方便!

替代文字

阿波罗缓存还有很多其他妙招。我们下次再讨论吧!

感谢推特用户@DrunkBB8提供原图。

文章来源:https://dev.to/akshar07/how-to-rock-the-party-with-apollo-graphql-cache-361l