如何使用 Apollo/GraphQL 使派生状态保持最新?
Posted
技术标签:
【中文标题】如何使用 Apollo/GraphQL 使派生状态保持最新?【英文标题】:How to keep derived state up to date with Apollo/GraphQL? 【发布时间】:2020-09-13 17:36:46 【问题描述】:我的情况是这样的:我的视图中有多个组件最终依赖于相同的数据,但在某些情况下,视图状态是从数据派生的。当基础数据发生变化时,如何确保我的整个视图保持同步?我将使用大家最喜欢的Star Wars API 举例说明。
首先,我显示一个所有电影的列表,查询如下:
# ALL_FILMS
query
allFilms
id
title
releaseDate
接下来,我想在 UI 中使用一个单独的组件来突出显示最近的电影。没有查询,所以我将使用客户端解析器来实现它。查询将是:
# MOST_RECENT_FILM
query
mostRecentFilm @client
id
title
以及解析器:
function mostRecentFilmResolver(parent, variables, context)
return context.client.query( query: ALL_FILMS ).then(result =>
// Omitting the implementation here since it's not relevant
return deriveMostRecentFilm(result.data);
)
现在,有趣的是 SWAPI 开始将 The Last Jedi 和 The Rise of Skywalker 添加到其电影列表中。我们可以假设我是列表中的polling,以便定期重新获取它。太好了,现在我的列表 UI 是最新的。但是我的“最近的电影”用户界面并没有意识到有什么变化——它仍然停留在 2015 年显示原力觉醒,尽管用户可以清楚地看到有更新的电影。
也许我被宠坏了;我来自MobX 的世界,像 Just Works™ 这样的东西。但这并不像一个不常见的问题。在 Apollo/GraphQL 领域是否有保持同步的最佳实践?我是否以完全错误的方式处理这个问题?
我的一些想法:
我的“最新电影”查询也可以定期轮询。但是您不想经常轮询;毕竟,星球大战电影每隔一年左右才会上映。 (谢谢,迪士尼!)根据轮询间隔的重叠方式,仍然会有一个很大的窗口让事情不同步。 而不是将deriveMostRecentFilm
逻辑放在解析器中,只需将其放在组件中并在组件之间共享ALL_FILMS
查询。那会起作用,但这基本上是在回答“我如何让它在阿波罗工作?”与“不要使用 Apollo”。
一些复杂的系统,用于跟踪查询之间的依赖关系并在此基础上链接刷新。 (如果可以避免的话,我不想发明这个!)
【问题讨论】:
【参考方案1】:在 Apollo 中,可观察对象(在组件中)超过查询值(缓存数据“槽”),但您的 mostRecentFilm
不是可观察对象,不是基于缓存值(它们被缓存)而是基于一次触发的查询结果(按需更新)。
您只是缺少一个“更新连接”,f.e.像这样:
# ALL_FILMS
query
allFilms
id
title
releaseDate
isMostRecentFilm @client
使用isMostRecentFilm
本地解析器更新缓存中的mostRecentFilm
值。
任何与mostRecentFilm @client
相关的查询 (useQuery
) 都会自动更新。所有这些都无需额外的查询、轮询等 - 可以正常工作吗? (未经测试,它应该可以工作);)
【讨论】:
所以要点是:计算原始查询旁边的派生值并将其作为对象保存在缓存中。现在它是缓存中的一个对象,可以观察到它。我相信这会奏效,但感觉很笨拙。现在不是将我的派生逻辑封装在它自己的解析器中,而是泄漏到另一个查询中。这是可行的,但听起来并不是最佳实践。 好吧,不是轮询,而是使用订阅......变化的来源是什么,发出什么消息,一些观察者在记录计数器或插入处理程序上?通常是最后一个(如果只有一个变化源,而不是共享数据库)......这不仅是派生状态,它是一种聚合器(所有记录)......还有什么?基于单项价值的上个月订单价值中位数?两者都应该是后端工作以上是关于如何使用 Apollo/GraphQL 使派生状态保持最新?的主要内容,如果未能解决你的问题,请参考以下文章
如何访问由点击事件触发的 apollo (GraphQL) 查询的状态
如何在 Apollo / GraphQL 发生突变后更新缓存?
Vuex 状态随突变而变化 - apollo graphql 查询
Redux-Logger 等效于 Apollo / Graphql