如何使用订阅和 AWS AppSync 高效同步 Apollo 的缓存
Posted
技术标签:
【中文标题】如何使用订阅和 AWS AppSync 高效同步 Apollo 的缓存【英文标题】:How to efficiently sync Apollo's cache using subscriptions and AWS AppSync 【发布时间】:2019-04-10 14:11:41 【问题描述】:我在 Node.js 客户端中使用 aws-appsync 来保存数据项的缓存列表。此缓存必须始终可用,包括未连接到 Internet 时。
当我的 Node 应用程序启动时,它会调用一个查询,该查询会从 AppSync 数据源返回整个项目列表。这是由 Apollo 的缓存存储缓存的,它允许未来的查询(使用相同的 GraphQL 查询)仅使用缓存进行。
该应用还订阅了能够修改其他客户端列表的突变。当列表中的项目发生更改时,新数据将发送到应用程序。这可以触发重新获取整个列表的原始查询,从而使缓存保持最新。
仅在一项更改时获取整个列表效率不高。 如何使缓存保持最新,同时最大限度地减少每次更改时必须获取的数据量?
解决方案必须提供一个访问缓存数据的单点。这可以是 GraphQL 查询或直接访问缓存存储。但是,不能使用来自多个查询的结果。
Apollo documentation 暗示这应该是可能的:
在某些情况下,仅使用 [自动商店更新] 不足以让您的应用程序...正确更新。例如,如果您想在不重新获取整个列表的情况下将某些内容添加到对象列表中...... Apollo Client 无法为您更新现有查询。
它建议的替代方案是重新获取(基本上是我上面描述的)并使用update
回调手动更新存储中的缓存查询结果。
使用
update
可以让您完全控制缓存,允许您以任何您喜欢的方式更改数据模型以响应突变。update
是查询后更新缓存的推荐方式。
但是,这里指的是同一客户端进行的突变,而不是使用订阅在客户端之间同步使用。 update
回调选项似乎不适用于订阅(提供更新的项目数据)或查询(可以获取更新的项目数据)。
【问题讨论】:
【参考方案1】:只要您的订阅包含已添加的全部资源,就应该可以通过直接读取和写入缓存来实现。假设我们从文档中有这样的订阅:
const COMMENTS_SUBSCRIPTION = gql`
subscription onCommentAdded
commentAdded
id
content
`;
Subscription 组件包含一个 onSubscriptionData
属性,因此我们应该能够按照以下方式做一些事情:
<Subscription
subscription=COMMENTS_SUBSCRIPTION
onSubscriptionData=( client, subscriptionData: data, error ) =>
if (!data) return
const current = client.readQuery( query: COMMENTS_QUERY )
client.writeQuery(
query: COMMENTS_QUERY,
data:
comments: [...current.comments, data.commentAdded],
,
)
/>
或者,如果您使用纯 javascript 而不是 React:
const observable = client.subscribe( query: COMMENTS_SUBSCRIPTION )
observable.subscribe(
next: (data) =>
if (!data) return
const current = client.readQuery( query: COMMENTS_QUERY )
client.writeQuery(
query: COMMENTS_QUERY,
data:
comments: [...current.comments, data.commentAdded],
,
)
,
complete: console.log,
error: console.error
)
【讨论】:
谢谢!对client.readQuery()
的引用让我得到了我想要的东西。请注意,我没有使用 React,因此我编辑了您的答案以包含一个纯 JS 选项。以上是关于如何使用订阅和 AWS AppSync 高效同步 Apollo 的缓存的主要内容,如果未能解决你的问题,请参考以下文章