【问题标题】:Angular 2+ refreshing real time data conditionally without refreshing the pageAngular 2+有条件地刷新实时数据而不刷新页面
【发布时间】:2018-05-18 01:44:15
【问题描述】:

我从 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();
    }
  }
}

【问题讨论】:

  • 你有几个嵌套订阅,这总是一种反模式,你只是从最近的刷新订阅中退订,你失去了对所有其他订阅的引用。
  • 问题是什么?你试过什么?您面临哪些问题?这不是一个“请修复我的代码”网站....
  • @bryan60 好的,我明白你的意思了,我会尝试取消订阅所有订阅
  • @olivarra1 你可以写,但我看不懂,我还是不明白。至少布莱恩非常清楚地理解我的问题。我什至没有要求你修复我的代码,我在这里通过解释问题而不是问像 1 + 1 = 之类的问题来问了很多问题。无需面对任何麻烦制造者(也许你想要这个)。谢谢你的投票,那么男人;)

标签: angular observable subscription


【解决方案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'
        });
}

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

【讨论】:

  • 我还没有尝试过您的解决方案,但我会尝试的。我想出了一个从服务中刷新数据的解决方案,但这个答案没有订阅(stackoverflow.com/questions/44947551/…)。正如 Bryan 上面所说的关于我的退订问题,我还通过这个答案 (stackoverflow.com/questions/38008334/…) 更新了退订方法。还是谢谢你。
  • 好吧,你的解决方案也很好用,我没有看到你所说的任何不良副作用
  • @HoàngNguyễn 那边的.do(...) 被称为“副作用”:Rxjs 操作符是纯粹的,所以你可以通过查看流的声明来了解整个情况。在两者之间使用this 被认为是一种不好的做法,最好想办法避免它。如果没有其他选择也没关系。很多时候,它们被完全接受(比如.switchMap(params =&gt; this.apiService.getTransaction(...)) 上的那个)。如果您不喜欢完美干净的代码,请不要太担心。
猜你喜欢
  • 2020-02-29
  • 1970-01-01
  • 2011-12-22
  • 2021-06-24
  • 2011-02-02
  • 2011-04-28
  • 2015-03-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多