问题标签 [apollo-cache-inmemory]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
0 回答
74 浏览

caching - Apollo 客户端中如何缓存 2 个非常相似的 Graphql 查询?

我正在阅读 Apollo 客户端文档,但我仍然对数据的缓存方式感到困惑。

假设我有 2 个查询,我在应用程序的不同层次结构级别使用它们。查询A用在最顶层,而查询B为下面几个级别的组件提供数据。

如果配置了 Apollo 缓存cache: new InMemoryCache()查询 B是否会使用查询 A中的Apollo 缓存数据?

如果我将查询 A用于顶部组件和底部组件,则同样的问题。

查询 A

查询 B

0 投票
1 回答
442 浏览

reactjs - Apollo GraphQL 缓存问题(cacheRedirects 和 readFragment)

我是 Apollo 和 Apollo 缓存的新手。我一直在写一个演示项目,遇到了两个问题:

  1. 无法cacheRedirects正常工作:

在我的演示中,我“加载所有”COVID19 测试数据,它查询 API 并返回包括加拿大在内的 3 个国家/地区的结果数组。然后我尝试加载单个结果(“加载加拿大”)以使其使用我的cacheRedirects解析器。我想我已经正确设置了这个,但它总是回到 API 来进行查询,而不是从缓存中读取。

这是我的带缓存的 Apollo 客户端:

  1. 我不知道如何执行readFragment

我在这段代码中尝试了很多不同的配置,但我从来没有得到任何结果。

这是我的功能:

额外问题:我似乎无法让 Apollo Client Developer Tools 扩展在 Chrome 浏览器中工作。这仍然有效吗?我的代码似乎从未连接到它。(取消注释掉connectToDevTools: true。)似乎能够检查缓存的内容对于开发和学习非常有用。是否有另一种查看缓存内容的方法?

0 投票
1 回答
145 浏览

caching - 在一个中等复杂的用例中,策略处理和使订阅的缓存数据失效

让我们以聊天应用程序为例。用户可以访问多个聊天线程,每个线程都有多条消息。用户界面由左侧的线程列表 ( listThreads) 组成,其中包含对方的姓名、最后一条消息、未读消息计数和最后一条消息的日期和时间,以及实际消息 ( viewThread) 和右侧的回复框(想想 facebook messenger)。

当用户选择一个消息线程时,viewThread组件订阅一个查询,如下所示:

为了进行实时更新,它q.subscriptToMore通过以下方式订阅:

这完美地工作,新消息按应有的方式显示。

为了列出可用的消息线程,查询所有线程的不太详细的视图:

为了使列表保持同步,使用相同的订阅,而不过滤thread_id,并且手动更新线程列表数据

这也很好用。

但是,如果选择了一个线程,则会缓存该线程A的消息。A如果B之后选择线程,则获取线程详细信息的查询的订阅将A被销毁,因为当路由器退出viewThread组件时,可观察对象被销毁。

A如果在用户查看线程时消息到达线程BthreadList则更新(因为该订阅是实时的),但如果用户切换回线程A,则从缓存中加载消息,这些消息现在已过时,因为没有订阅将更新或使缓存无效的特定消息线程。

在用户导航到完全不同的页面的其他情况下,线程列表不会出现在视图中,问题更加明显,因为没有任何与积极订阅的聊天消息相关的内容,因此没有任何内容可以使缓存数据无效当有新消息到达时,尽管服务器理论上提供了一种通过提供新消息订阅事件来做到这一点的方法。

我的问题如下:

保持 Apollo 缓存的数据同步/无效的最佳实践是什么,这些数据并未积极“使用”?保持嵌套数据同步的最佳实践是什么(事件线程的消息 [见下文])。我觉得不必在事件查询中实现有关如何订阅和更新消息数据的逻辑是一个干净的解决方案。

使用.subscribeToMore可以使积极使用的数据保持同步,但是一旦不再使用该查询,数据就会保留在缓存中,这些数据可能会随着时间的推移而过时,也可能不会过时。当可观察对象超出范围时,有没有办法删除缓存的数据?只要至少有一个查询使用它,就保持这些数据缓存,因为我相信它还实现了基于服务器推送事件保持同步的逻辑。

是否应该使用订阅(通过 SPA 的整个生命周期)所有订阅事件并包含有关如何更新每种类型的缓存数据(如果存在于缓存中)的知识的服务?(可以通知该服务哪些数据需要保持同步以避免使用不必要的资源)(如在订阅所有newMessage事件并基于此戳缓存的服务中)?这会自动为返回的对象引用此类数据的查询发出新值吗?(更新是否message:1会使在其消息字段中返回相同的线程查询message:1自动发出一个新值)或者这些查询也必须手动更新?

这在扩展这个模型时开始变得非常麻烦,说Events也有自己的聊天线程,所以event { thread { messages { ... } }现在查询需要订阅newMessage订阅,这打破了封装和单一责任原则。订阅newMessage数据需要提供与事件关联的消息线程的 id 也是有问题的,但在查询返回之前这是不知道的。由于这个.subscribeToMore不能使用,因为那时我还没有thread_id可用的。

0 投票
1 回答
327 浏览

graphql - GraphQL:Apollo 客户端缓存如何工作以保持与服务器的数据一致性?

我正在apollo-client使用apollo-cache-inmemory.

假设我有 2 个页面:项目列表页面和项目详细信息页面。

显示项目列表页面(通过使用以下方式获取数据client.query(...)

  • 项目 A
  • B项
  • 项目 C

当导航到项目 B 的项目详细信息store.readQuery页面时,我使用涉及并store.writeQuery在此处描述的突变技术对项目 B 进行了突变: https ://www.apollographql.com/docs/react/caching/cache-interaction/#updating-after-a -突变

现在,在导航回项目列表页面之前,假设我的应用程序的另一个用户对项目 A 进行了突变。

我的问题:

  1. 当我导航回项目列表页面时,我是从缓存中获取数据还是从服务器获取数据?是否client.query(...)总是从服务器获取数据?

  2. 如果我从缓存中获取数据,我该如何保持与服务器的数据一致性?(目标是始终在列表中显示更新的项目,例如项目 A - 在优化缓存的同时与服务器同步)

0 投票
1 回答
1802 浏览

caching - Apollo Client v3 在给定时间段后删除缓存条目

我想知道是否有办法在某个时间段(例如 24 小时)后使缓存项目过期。

我知道 Apollo Client v3 提供了 和 等方法cache.evictcache.gc这是一个好的开始,我已经在使用;但是,我想要一种在给定时间段后删除缓存项的方法。

我现在正在做的是为我的 Apollo 模式中的每个对象添加一个 TimeToLive 字段,当后端返回一个对象时,该字段将填充当前时间 + 24 小时(即 24 小时时间)。然后当我在前端查询数据时,我检查返回数据的 TimeToLive 字段是否在未来(如果不是,则意味着数据肯定是从缓存中检索的,在这种情况下我调用refetch函数,这会强制查询从服务器获取数据.但是,这似乎不是最好的方法,主要是因为我必须遍历返回的数据中的每个结果并检查是否有任何返回的对象过期; 如果是这样,则重新获取所有内容。

我想到的另一个解决方案是使用React Native Queue之类的东西,并有一个后台任务定期检查缓存并删除已过期的项目。但同样,我并不完全相信这个解决方案。

这里有一点上下文:我正在构建一个烹饪/食谱应用程序 - 并且食谱/帖子缓存在设备上;但是,我担心的是用户可以删除帖子,但是缓存了该帖子的其他所有人仍然可以看到它,因此通过使缓存的项目过期至少他们只能看到几个小时在它被移除之前。但是,它们可能是一起完成这一切的更好方法,即让服务器与缓存项目联系客户端(尽管在撰写本文时我想不出任何低升程解决方案)

0 投票
1 回答
158 浏览

react-apollo - 查询变量更改时 Apollo 缓存失败

我正在使用 useLazyQuery() 来获取由时间过滤器测量的分析数据。当时间过滤器更改时,缓存会返回相同的值,尽管有过滤器。

我正在使用默认的 fetchPolicy(缓存优先)。

谢谢并恭祝安康!

0 投票
0 回答
135 浏览

apollo-client - 在 ROOT_QUERY 对象上找不到字段 reportModuleById

我有以下查询:

在某些时候,我将报告模块写入缓存:

然后稍后我尝试使用以下命令从缓存中读取它readQuery

我在整个应用程序中成功地使用writeQuery和相同的方式。readQuery但是这次我看到一条错误消息:“在 ROOT_QUERY 对象上找不到字段 reportModuleById”。

奇怪的是数据实际上在缓存中:

阿波罗缓存.png

这几天我一直在努力解决这个问题,这里有什么我想念的吗?

0 投票
0 回答
243 浏览

reactjs - Apollo Client:使用默认值初始化缓存的最佳实践?

我搜索了很多关于使用 Apollo Client 进行本地状态管理的教程。

要使用一些初始化值初始化缓存,从这个示例中,我可以使用typePolicies. 通过定义这样的反应变量:

此外,我还看到了cache.writeData({ data: initialState });在创建客户端后初始化的教程。

我很想知道区别,以及哪个是首选。

0 投票
1 回答
733 浏览

javascript - 如何在 Apollo 客户端 InMemoryCache 中获取和设置新缓存的相关对象的 ref?

我有一组相关的项目,如下所示:

其中 apollo 缓存为两个单独的缓存对象,其中related_entity字段 onbookEntityNode对象的引用。这很好,相关实体数据也在 a 上下文之外的其他地方使用,book所以让它分开工作,一切看起来都很好,并且按预期更新......除非相关实体不存在于初始提取(因此book对象上的 ref 为空),我稍后创建一个。

我尝试向钩子添加一个update函数,根据他们的文档useMutation创建上述内容: https ://www.apollographql.com/docs/react/caching/cache-interaction/#example-adding-an-item-to-a -像这样的列表:related_entity

但无论我似乎尝试什么,newEntityRef总是未定义,即使新的 EntityNode 肯定在缓存中并且可以使用完全相同的片段很好地读取。我可以放弃并强制重新获取 Book 对象,但数据已经在那里了

我做错了什么/有更好的方法吗?除非你有它的标识符,否则是否有另一种方法来获取缓存对象的引用?

0 投票
1 回答
939 浏览

caching - 当来自服务器的响应为空列表时,Apollo Client refetch() 不会更新缓存

每当 useQuery 的变量发生变化时,我都会使用refetch()它来过滤列表。每次更改变量 prop 时,它都会根据过滤器获取结果,当来自服务器的结果为空列表 [] 时,refetch() 方法返回缓存结果而不是空列表 []。

因此,每次 userNum 属性随具有此 userNum 的用户列表发生更改时,它都会获取更新的结果,但是,如果从服务器返回的用户列表为空(因为没有用户拥有此编号),我可以看到以前的缓存结果一个空列表。

我努力了

并且仍然得到缓存的结果而不是空列表。

我还尝试了 typePolicies 中的 merge() 并且它有效!但是,当我应用 relayStylePagination 时,它会再次获取缓存的结果而不是空列表。

我也尝试过使用 keyfields 并且再次工作缓存在服务器返回空列表时更新,但是中继分页不起作用。让中继分页工作的唯一方法是像这样放置它:

` 我的查询是这样的:

系统详情: