简体   繁体   English

使用switchMap的Angular 4 RxJS轮询

[英]Angular 4 RxJS polling with switchMap

I recently asked a question related to subscriptions being lost if switchMap encountered an error: 我最近问了一个问题,如果switchMap遇到错误,则与订阅丢失有关的问题:

Angular 4 losing subscription with router paramMap using switchMap Angular 4使用SwitchMap的路由器paramMap失去订阅

The solution was to return an empty Observable as once an Observable hits an error the subscription will be destroyed. 解决方案是返回一个空的Observable,因为一旦Observable遇到错误,订阅将被销毁。

I now need to figure out how to poll with the same code but stop polling once the API returns data - I believe returning this empty Observable is causing my polling code to not work as expected. 现在,我需要弄清楚如何使用相同的代码进行轮询,但是一旦API返回数据,就必须停止轮询-我相信返回此空的Observable会导致我的轮询代码无法正常工作。

Current code WITHOUT POLLING: 当前代码无查询:

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
  }
}

Proposed code WITH POLLING: 建议的带轮询代码

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. switchMap on route.paramMap, meaning any previous Observables are cancelled route.paramMap上的switchMap,这意味着所有先前的Observable都将被取消
  2. return new Observable that has interval of 10 seconds and starts immediately 返回间隔为10秒并立即开始的新Observable
  3. flatMap the HTTP request and polling Observables flatMap HTTP请求并轮询Observables
  4. filter the incoming data, if it has a property of Interval then take it and stop polling 过滤传入的数据,如果它具有Interval的属性,则将其接收并停止轮询
  5. map returns a new observable thats needed for the subscribe 地图返回订阅所需的新的可观察到的多数民众赞成在
  6. the catch is there returning an empty observable to handle the original issue 渔获物返回一个空的可观察值以处理原始问题

This code is always taking the first result (with the use of take(1)) however it was my understanding that if you filter first you can pragmatically only take the first result that is valid (in my case has a valid response). 这段代码始终采用第一个结果(使用take(1)),但是据我的理解,如果您首先进行过滤,则可以务实地仅采用有效的第一个结果(在我的情况下具有有效的响应)。

This is my current, limited understanding and believe there are clearly gaps in my knowledge so I'm attempting to learn more about how chaining of these operators and Observables works. 这是我目前有限的理解,并认为我的知识显然存在不足,因此我试图更多地了解这些运算符和Observable的链接方式。

So after more research on how RxJS Observables function I found that I shouldn't be letting the error 'propagate' through the chain and effectively cancel my subscription. 因此,在对RxJS Observables的功能进行了更多研究之后,我发现我不应该让错误“传播”通过链并有效地取消我的订阅。 I also simplified my code: 我还简化了代码:

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
  });
}

I'm think I could swap out the second switchMap operator with flatMap but I want to ensure the previous (outer) Observable is cancelled. 我认为我可以将第二个switchMap运算符与flatMap换出,但是我想确保取消先前的(外部)Observable。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM