2017-09-05 125 views
4

我有一个屏幕,需要呈现一些不断变化的数据从一个API。在我的API调用的可见性中,我使用repeatWhen()来实现轮询。此外,当我检测到传入数据的某些值发生变化时,我需要做一个额外的API调用。我目前的执行情况是这样工作的:防止多次执行可观察

let queueStatusObservable = this.enumService.getOptions('WorkQueueStatus'); 
    let queueItemObservable = this.enumService.getOptions('WorkItemStatus'); 

    // retrieve status every 3000ms 
    let summaryObservable = this.service 
     .getSummary(this.id) 
     .repeatWhen(completed => completed.delay(3000)); 

    this.summaryModel$ = Observable.combineLatest(queueStatusObservable, queueItemObservable, summaryObservable) 
     .map(results => { 
      let workQueueStatusList = results[0]; 
      let workItemStatusList = results[1]; 
      let summary = results[2].status > -1 ? results[2] : null // convert empty {} object to null; 

      let model = { 
       workQueueStatusList: workQueueStatusList, 
       workItemStatusList: workItemStatusList, 
       summary: summary 
      }; 

      return model; 
     }); 

    // fetch validationmessages every time the count changes 
    this.validationMessages$ = Observable.merge(
     summaryObservable.first((value, index) => value.statusCount['Invalid'] > 0), 
     summaryObservable.pairwise().filter((value, index) => value[0].statusCount['Invalid'] != value[1].statusCount['Invalid']) 
    ).flatMap(i => me.service.getMessages()); 

    // fetch errors every time the count changes 
    this.errorMessages$ = Observable.merge(
     summaryObservable.first((value, index) => value.statusCount['Error'] > 0), 
     summaryObservable.pairwise().filter((value, index) => value[0].statusCount['Error'] != value[1].statusCount['Error']) 
    ).flatMap(i => me.service.getErrors()); 

没有订阅()调用的观测,因为那些使用异步管我的角模板发生,像这样:

<div *ngIf="summaryModel$|async; let summaryModel"> 

我预计,我会每3秒收到一次api调用,并且所有在summaryObservable上工作的语句都将仅由此api调用响应触发。

它似乎并没有这样工作。当我在铬合金中打开网络标签时,我发现我每3秒收到4个API调用。这是rxjs应该如何工作,或者我以错误的方式使用rxjs?

我结束了解决的办法是:

let summaryObservable = this.service 
    .getSummary(this.id) 
    .repeatWhen(completed => completed.delay(3000)) 
    .shareReplay(); 

使用共享的方法,我不需要管理连接/ deconnecting自己,和shareReplay确保每一个值可以要求多倍。

+0

所以,你有多个'summaryModel $ |在async'您模板? – martin

+1

要开始,如果它在同一模板中,可以使用as语法。像'* ngIf =“obs $ | async as obs”'然后在一个订阅的obs上工作。另外,您可能想要搜索如何使用rxjs中的'share'运算符。 – Maxime

回答

2

您正在使用相同的summaryObservable 5个不同的时间。其中2个是一次性使用first调用。这会给你带来3种不同的用途。

当您想多次重复使用相同的可观察元素时,您需要使用类似publish的东西来“共享”具有所有用途的观察值的单个订阅。

尝试是这样的:

let summaryObservable = this.service 
    .getSummary(this.id) 
    .repeatWhen(completed => completed.delay(3000)) 
    .publish(); // creates a ConnectableObservable 

// ... 
// all the rest of your code goes here 
// ... 

// Finally "connect" the observable to start the polling 
// that will be shared by all the other usages 
this.summaryConnection = summaryObservable.connect() 

并确保您定义ngOnDestroy停止投票时,您的组件被破坏:

ngOnDestroy() { 
    this.summaryConnection.unsubscribe(); // .dispose() if using older version of RXJS 
}