0

我在 Node.js 客户端中使用 aws-appsync 来保留数据项的缓存列表。此缓存必须始终可用,包括未连接到 Internet 时。

当我的 Node 应用程序启动时,它会调用一个查询,该查询会从 AppSync 数据源返回整个项目列表。这是由 Apollo 的缓存存储缓存的,它允许将来的查询(使用相同的 GraphQL 查询)仅使用缓存进行。

该应用程序还订阅了能够修改其他客户端列表的突变。当列表中的项目发生更改时,新数据将发送到应用程序。这可以触发重新获取整个列表的原始查询,从而使缓存保持最新。

当只有一项更改时获取整个列表效率不高。如何使缓存保持最新,同时最大限度地减少每次更改时必须获取的数据量?

该解决方案必须提供一个访问缓存数据的单点。这可以是 GraphQL 查询,也可以是直接访问缓存存储。但是,不能选择使用来自多个查询的结果。


Apollo 文档暗示这应该是可能的:

在某些情况下,仅使用 [自动商店更新] 不足以让您的应用程序......正确更新。例如,如果您想在不重新获取整个列表的情况下将某些内容添加到对象列表中...... Apollo Client 无法为您更新现有查询。

它建议的替代方案是重新获取(基本上是我上面描述的)并使用update回调手动更新存储中的缓存查询结果。

Usingupdate使您可以完全控制缓存,允许您以任何您喜欢的方式对数据模型进行更改以响应突变。update是查询后更新缓存的推荐方式。

但是,这里指的是同一客户端进行的突变,而不是使用订阅在客户端之间同步使用。update回调选项似乎不适用于订阅(提供更新的项目数据)或查询(可以获取更新的项目数据)。

4

1 回答 1

1

只要您的订阅包含已添加的全部资源,就应该可以通过直接读取和写入缓存来实现。假设我们从文档中有这样的订阅:

const COMMENTS_SUBSCRIPTION = gql`
  subscription onCommentAdded {
    commentAdded {
      id
      content
    }
  }
`;

Subscription 组件包含一个onSubscriptionDataprop,因此我们应该能够按照以下方式做一些事情:

<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
})        
于 2018-11-07T13:14:16.937 回答