Angular 2+有条件刷新实时数据而无需刷新页面

时间:2017-12-04 14:49:32

标签: angular observable subscription

我从API服务获得交易,条件是交易状态为“待定”,继续重新加载和订阅交易,直到交易状态为“已完成”或“已拒绝”。我的代码只能在第一次工作,然后下次访问时,页面是空白的,但数据仍然在控制台中运行,即使我取消订阅它。

这是我的代码:

export class TransactionSummaryComponent implements OnInit, OnDestroy {

  transaction: Models.Transaction = <Models.Transaction>{};

  cancelling: boolean = false;
  goToPayment: boolean = false;

  private dataRefreshSub: Subscription;
  private subscribeToDataSub: Subscription;
  private timer: Observable<any>;

  constructor(
    private route: ActivatedRoute,
    private router: Router,
    private apiService: ApiService,
    private zone: NgZone,
    @Inject(PLATFORM_ID) private platformId: Object) { }

  ngOnInit() {
    if (isPlatformBrowser(this.platformId)) {
      this.getTransaction();
    }
  }

  getTransaction() {
    this.route.paramMap
    .switchMap((params: ParamMap) => this.apiService.getTransaction(params.get('id')))
    .subscribe((transaction: Models.Transaction) => {
      this.transaction = transaction;

      if (this.transaction.status === 'Pending') {
        this.refreshData();
      }
    });
  }

  refreshData() {
    this.dataRefreshSub = this.route.paramMap
      .switchMap((params: ParamMap) => this.apiService.getTransaction(params.get('id')))
      .subscribe((transaction: Models.Transaction) => {
        this.transaction = transaction;
        this.subscribeToData();
      });
  }

  subscribeToData() {
    this.zone.runOutsideAngular(() => {
      NgZone.assertNotInAngularZone();
      this.timer = Observable.timer(1, 5000);
      this.subscribeToDataSub = this.timer
        .subscribe(() => {
          this.refreshData();
        });
    });
  }

  ngOnDestroy() {
    if (this.dataRefreshSub !== undefined) {
      this.dataRefreshSub.unsubscribe();
    }
    if (this.subscribeToDataSub !== undefined) {
      this.subscribeToDataSub.unsubscribe();
    }
  }
}

1 个答案:

答案 0 :(得分:1)

我无法提出不使用副作用的解决方案,但我认为它可能对您有所帮助。 Rxjs有一个retry()运算符,它会在抛出时重新运行订阅。所以我会做这样的事情:

getTransaction() {
    this.route.paramMap
        .switchMap((params: ParamMap) => this.apiService
            .getTransaction(params.get('id'))
            .do(transaction => this.transaction = transaction) // Bad side effect here, I'm not sure how can this be cleaned out.
            .map(transaction => {
                if(transaction.status === 'Pending') {
                    throw 'Pending';
                }
                return transaction;
            })
            // use .retry(N) to retry at most N times. This will infinitely retry
            .retryWhen(errors => errors)
        )
        .subscribe((transaction: Models.Transaction) => {
            // Here transaction will be 'Completed' or 'Rejected'
        });
}

有了这个,您可以理论上删除所有其他订阅。