我在Node.js客户端中使用aws-appsync来保存缓存的数据项列表。此缓存必须始终可用,包括未连接到internet时。
当我的Node应用程序启动时,它会调用一个查询,返回AppSync数据源中的整个项目列表。这是由Apollo的缓存存储缓存的,它允许未来的查询(使用相同的GraphQL查询(只使用缓存进行。
该应用程序还订阅了突变,这些突变可以在其他客户端上修改列表。当列表中的项目发生更改时,新数据将发送到应用程序。这可以触发重新获取整个列表的原始查询,从而使缓存保持最新。
当只有一个项目发生更改时,获取整个列表是无效的如何使缓存保持最新,同时最大限度地减少每次更改所需的数据量
该解决方案必须提供一个访问缓存数据的单点。这可以是GraphQL查询,也可以直接访问缓存存储。但是,不能选择使用多个查询的结果。
Apollo文档暗示这应该是可能的:
在某些情况下,仅使用[自动存储更新]对您的应用程序来说是不够的。。。以正确更新。例如,如果你想在不重新绘制整个列表的情况下向对象列表中添加一些内容。。。Apollo客户端无法为您更新现有查询。
它建议的替代方案是重新蚀刻(基本上就是我上面描述的(,并使用update
回调手动更新存储中缓存的查询结果。
使用
update
可以完全控制缓存,允许您以任何方式更改数据模型以应对突变。update
是在查询之后更新缓存的推荐方式。
然而,这里它指的是由同一客户端进行的突变,而不是使用订阅在客户端之间同步。update
回调选项似乎不可用于订阅(提供更新的项目数据(或查询(可以获取更新的项目信息(。
只要您的订阅包含已添加的全部资源,就可以直接从缓存中读取和写入。让我们假设我们从文档中订阅了这样一个:
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
})