角度服务可实时将可观察对象/对象从缓存阵列返回到组件的多个实例

时间:2019-06-03 13:56:46

标签: angular caching rxjs observable angular7

使用案例

BlogComponents with Multiple <code>UserActionsComponent</code>s each

我有一个内容页面,其中包含UserActionsComponent的多个实例。我还有一个全局DataService,它充当具有(想要)高级缓存的数据提供程序。

数据获取层次结构:

内存缓存>>浏览器存储(异步)>> HTTP请求

UserActionsComponent

请求dataService.getData(URL,params,method)

PS:params具有类似blogId之类的详细信息,这使哈希签名变得唯一

DataService(.getData())

1)使用诸如genUniqueHash(URL + stringify(params)+ method)之类的东西制作唯一的哈希键

2)检查内存缓存中是否存在值(数组[KEY])-如果是,则返回ob $

3)检查浏览器的存储中是否存在值(异步;使用离子存储)-如果是,则返回ob $ else-保存到内存缓存中,然后返回ob $(array [KEY])

4)从HTTP调用获取值,保存到存储,保存到内存中的缓存并返回ob $(array [KEY])

此概念不起作用,因为我无法弄清楚如何从缓存值数组中返回共享的可观察对象(我猜这应该是BehaviourSubject?)。请带我去正确的轨道。

注释

  • 如果用户对一个组件投了赞成票,则它必须反映视图中的所有其他实例(所有特定Blog条目的UserActionsComponent应该更新)
  • 在同一页面上的一个视图中可以有许多UserActionsComponent(例如:对于BlogEntry#1和BlogEntry#25)!
  • 随着用户访问新的Blog帖子,内存中的缓存不断增长(这很好,因为它是一个有限的集合)

我是RxJS的菜鸟。我尝试过运气:

  • pipe(share())[由于它是一项服务,因此该管道已与所有URL共享]
  • 返回(cache [key])[不能工作,因为最后获取的BlogEntry的用户操作会反映所有订阅]
  • 返回整个缓存,然后在UserActionsComponent端过滤出所需的数据(使用array [KEY])(这是当前实现)

当前的实现有效,但是对于这种用例,这似乎并不是最好的方法。原因是:一个视图可能具有多达20个UAC [UAC-A(1),UAC-B(1),UAC(200)...]。 UAC发出两次next()。 UAC的onInit以及用户在UAC中上投票或下票的时间。现在,由于更改,我们发出缓存数据,此页面视图的大小为20的数组发出2 * 20次。

使用RxJS实现此目的的最优化方法是什么?

2 个答案:

答案 0 :(得分:0)

您只能选择一个主题/行为主题。以可观察的方式返回它,每个UAC都可以订阅并侦听数据。现在,我假设每个UAC都必须附加一些唯一的标识符,比方说一个博客ID。因此,当您使用Subject发出数据以及数据时,也要在该数据中附加该博客ID。在UAC匹配中,如果UAC的ID与从observable接收到的ID相同,则更新UAC中的数据,否则忽略。这样,正确的UAC将被更新。 例如:-

data.service.ts

const a = new BehaviourSubject();

getDataSource() {
 return a.asObservable():
}

cacheCheck(blogId: string) {
  // emit the data with a blogId.
  a.next({'id': blogId, 'data': getDataFromSomeWhere()})
}

blog.component.html

<app-uac [id]="blogId"></app-uac>

uac.component.ts

@Input id: string;
constructor(public dataService: DataService) {}
ngOnInit() {
   dataService.getDataSource().subscribe((data) => {
      if(data.id == this.id) //do somethin in UAC or emit event to parent
         //blog and let it do something
      else { //ignore}
   })
}

这条线上的东西。

答案 1 :(得分:0)

当前实施:

写下来,因为这对将来的人会有所帮助。 我设法通过可观察的模式对其进行了优化:

  • UAC onInit()调用dataService.getData(url,params,method,guid)
  • UAC传递的guid是服务的缓存键
  • UAC有两个来自dataService的订阅。一个是dataService.getData方法,该方法返回一个可观察的对象-主要用作设置guid的初始化程序-在使用.pipe(first())获取其第一个值后便取消订阅。第二个订阅是一个名为dataChanged的BehaviourSubject。每当dataService缓存上的数据发生更改时,它都会发出dataChanged.next(newDataDelta)。该订阅将一直持续到组件的onDestroy。
  • dataService按cache[guid] > storage[guid] > http[url]进行分层检查,相应地设置数据,最后调用dataChangedSubj.next(cache[guid]) 仅会发出更改的增量
  • 所有UAC均接收新的缓存数据集(即cache [guid];仅包含已更改的内容),并检查receivedData[guid]以查看发出的数据是否与UAC相关。如果是,它将消耗掉它。
  • 如果用户对UAC进行投票/否决,则UAC会进行必要的API调用,并在成功后执行dataService.updateData(guid,data),而该服务随后使用dataChanged.next(newDataDelta)发出更改所有UAC和属于同一博客文章的UAC都会更新其数据(因为它们的GUID相同)

仍然开放使用RxJS来实现此用例的最佳方法。