【问题标题】:Angular 4 RxJS polling with switchMapAngular 4 RxJS 使用 switchMap 轮询
【发布时间】:2018-02-22 01:29:43
【问题描述】:

我最近问了一个关于如果 switchMap 遇到错误会丢失订阅的问题:

Angular 4 losing subscription with router paramMap using switchMap

解决方案是返回一个空的 Observable,因为一旦 Observable 遇到错误,订阅就会被销毁。

我现在需要弄清楚如何使用相同的代码进行轮询,但在 API 返回数据后停止轮询 - 我相信返回这个空的 Observable 会导致我的轮询代码无法按预期工作。

当前代码没有轮询:

ngOnInit() {
  this.subscription = this.route.paramMap
    .switchMap( (params) => {
      this.setChartDefaults();
        return this.getForecastData(params.get('id'))
    .do(null, (err) => {
      this.errorText = err.statusText
      this.loading = false;
    })
    .catch( () => { return Observable.empty() });
  })
}

ngAfterViewInit() {
  this.subscription.subscribe( (data) => {
    // business logic
  }
}

提议的代码有轮询:

ngOnInit() {
  this.subscription = this.route.paramMap
    .switchMap( (params) => {
      return Observable
      .interval(10000)
      .startWith(0)
      .flatMap( () => {
        return this.getForecastData(params.get('id'))
      })
      .filter( (val) => {
        return val.Interval != null
      })
      .take(1)
      .map((forecast) => forecast)
      .do(null, (err) => {
        this.errorText = err.statusText
        this.loading = false;
      })
      .catch( () => { return Observable.empty() });
  })
}

ngAfterViewInit() {
  this.subscription.subscribe( (data) => {
    // business logic
  }
}
  1. route.paramMap 上的 switchMap,这意味着任何以前的 Observable 都被取消了
  2. 返回间隔为 10 秒并立即启动的新 Observable
  3. flatMap HTTP 请求和轮询 Observables
  4. 过滤传入的数据,如果它具有 Interval 属性,则接受它并停止轮询
  5. map 返回订阅所需的新可观察对象
  6. 问题在于返回一个空的 observable 来处理原始问题

此代码始终采用第一个结果(使用 take(1))但是我的理解是,如果您首先过滤,您实际上可以只采用第一个有效的结果(在我的情况下有一个有效的响应)。

这是我目前的有限理解,我认为我的知识显然存在差距,因此我正在尝试更多地了解这些运算符和 Observable 的链接如何工作。

【问题讨论】:

  • 所以它不起作用怎么办?或者这段代码应该做什么?您正在使用take(1),因此Observable.interval 始终只发出一项,然后链就完成了。
  • 抱歉,已为问题添加了更多详细信息。

标签: javascript angular rxjs observable


【解决方案1】:

因此,在对 RxJS Observables 的功能进行了更多研究后,我发现我不应该让错误通过链“传播”并有效地取消我的订阅。我还简化了我的代码:

public getForecastData(forecastId) : Observable<any> {
  return this.http
    .get<any>('/api/forecasts/' + forecastId)
    .map( res => res)
    .catch( () => Observable.empty());
}

ngOnInit() {
  let $pollObservable = Observable
    .interval(8000)
    .startWith(0);

    this.subscription = this.route.paramMap
      .switchMap( (params) =>
        $pollObservable
        .switchMap( () => {
          this.setChartDefaults();
          return this.getForecastData(params.get('id'))
        })
      .filter( (val) => {
        return val.Interval != null
      })
      .take(1)
      .map( forecast => forecast)
      )
}

ngAfterViewInit() {
  this.subscription.subscribe( (data) => {
    // business logic
  });
}

我想我可以用 flatMap 替换第二个 switchMap 运算符,但我想确保取消前一个(外部)Observable。

【讨论】:

    猜你喜欢
    • 2016-05-02
    • 1970-01-01
    • 2018-03-18
    • 1970-01-01
    • 1970-01-01
    • 2016-12-18
    • 1970-01-01
    • 1970-01-01
    • 2022-01-16
    相关资源
    最近更新 更多