防止多次执行可观察的

时间:2017-09-05 11:27:22

标签: angular rxjs

我有一个屏幕需要从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());

对observables没有subscribe()调用,因为那些使用异步管道在我的角度模板中发生,如下所示:

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

我预计我会每3秒钟进行一次api调用,并且所有使用summaryObservable的语句都只会被这个api调用响应触发。

它似乎没有这样的方式。当我打开chrome中的网络选项卡时,我看到我每3秒钟收到4次api通话。这是rxjs应该如何工作,还是我以错误的方式使用rxjs?

我最终得到的解决方案是:

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

使用共享方法,我不需要自己管理连接/断开连接,而shareReplay确保可以多次请求每个值。

1 个答案:

答案 0 :(得分:3)

您正在使用相同的summaryObservable 5次不同的时间。其中2个是仅限一次性first次呼叫。这通常会让你有三种不同的用途。

如果要多次重复使用相同的observable,则需要使用类似publish的内容来“共享”具有所有用途的observable的单个订阅。

尝试这样的事情:

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
}
相关问题