在中等复杂的用例中,策略处理和使订阅中的缓存数据无效

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

当用户选择消息线程时,viewThread组件按照以下方式订阅查询:

  query thread {
    threads(id: 'xxxx') {
      id
      other_party { id name }
      unread_messages
      messages { 
        sent_by { id } 
        timestamp
        text
      }
  }

要进行实时更新,请设置q.subscriptToMore并按以下方式进行订阅:

  subcription newMessages {
    newMessage(thread_id: 'xxx') {
        sent_by { id } 
        timestamp
        text    
    }
  }

这很好用,新消息按原样显示。

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

  query listThreads {
    threads {
      id
      other_party { id name }
      unread_messages
      last_updated_at
    }
  }

为使列表保持同步,使用了相同的订阅,而没有在thread_id上进行过滤,并且线程列表数据是手动更新的

这也很好。

但是,如果选择了线程A,则会缓存线程A的消息。 如果此后选择了线程B,则将破坏获取线程A的详细信息的查询订阅,因为当路由器交换viewThread组件时,observable被破坏了。

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

在其他情况下,用户导航到一个完全不同的页面,在该页面中看不到线程列表,该问题甚至更加明显,因为没有任何与活动订阅的聊天消息相关的内容,因此也没有任何无效的消息尽管从理论上说服务器是通过提供新的消息订阅事件来实现此目的的,但是当新消息到达时,缓存的数据仍会保留。

我的问题如下:

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

使用.subscribeToMore可保持主动使用的数据同步,但是一旦不再使用该查询,数据将保留在高速缓存中,这可能会或可能不会随着时间而过时。当可观察对象超出范围时,是否可以删除高速缓存的数据?与之一样,只要至少有一个查询在使用该数据,就保留它的高速缓存,因为我相信它还实现了根据服务器推送事件保持同步的逻辑。

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

当使用说说Events扩展这个模型并且也有自己的聊天线程时,这变得非常麻烦,因此查询event { thread { messages { ... } }现在需要订阅newMessage订阅,这将破坏封装以及单一责任原则。 订阅newMessage数据还需要提供与事件关联的消息线程的ID,但这在查询返回之前是未知的,这也是一个问题。由于此.subscribeToMore无法使用,因为那时我还没有thread_id

chenyuhui22 回答:在中等复杂的用例中,策略处理和使订阅中的缓存数据无效

如果预期的行为是“每次我打开线程时,都显示最新消息,而不仅仅是缓存内容”,则只需将fetchPolicy查询的thread设置为{{ 1}},这将确保始终将请求发送到服务器,而不是从缓存中实现。 network-only的文档缺少有关此选项的信息,但这是React docs的说明:

有效的fetchPolicy值为:

  • apollo-angular:这是默认值,我们始终尝试首先从您的缓存中读取数据。如果满足查询所需的所有数据都在高速缓存中,则将返回该数据。仅当没有缓存结果时,Apollo才会从网络获取。此提取策略旨在最大程度地减少渲染组件时发送的网络请求。
  • cache-first:此提取策略将使Apollo首先尝试从缓存中读取数据。如果满足查询所需的所有数据都在高速缓存中,则将返回该数据。但是,无论缓存中是否有完整数据,该fetchPolicy始终会通过网络接口执行查询,这与缓存优先不同,后者仅在查询数据不在缓存中时才执行查询。此提取策略可优化用户的响应速度,同时还可以使缓存的数据与服务器数据保持一致,但需要额外的网络请求。
  • cache-and-network:此提取策略将永远不会从缓存返回初始数据。相反,它将始终使用您的网络接口向服务器发出请求。这种获取策略可优化与服务器的数据一致性,但是会以可用时对用户的即时响应为代价。
  • network-only:此提取策略将永远不会使用您的网络接口执行查询。相反,它将始终尝试从缓存中读取。如果用于查询的数据在缓存中不存在,则将引发错误。此获取策略允许您仅与本地客户端缓存中的数据进行交互,而无需发出任何网络请求,从而使组件保持快速运行,但是这意味着您的本地数据可能与服务器上的数据不一致。如果只对与ApolloClient缓存中的数据进行交互感兴趣,还请确保查看ApolloClient实例上可用的readQuery()和readFragment()方法。
  • cache-only:此提取策略将永远不会从缓存中返回您的初始数据。相反,它将始终使用您的网络接口向服务器发出请求。与仅限网络的策略不同,查询完成后,它也不会将任何数据写入缓存。
本文链接:https://www.f2er.com/2312141.html

大家都在问