Недавно я задал вопрос, связанный с утерями подписки, если switchMap обнаружил ошибку:
Угловая 4 проигрывает подписку с маршрутизатором paramMap с помощью switchMap
Решение состояло в том, чтобы вернуть пустое Наблюдаемое, как только Наблюдатель ударит по ошибке, что подписка будет уничтожена.
Теперь мне нужно выяснить, как опросить один и тот же код, но прекратить опрос, как только 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
}
}
Этот код всегда принимает первый результат (с использованием take (1)), однако я понял, что если вы сначала фильтруете, вы можете прагматически принять только первый результат (в моем случае есть действительный ответ).
Это мое текущее, ограниченное понимание и считаю, что в моих знаниях явно имеются пробелы, поэтому я пытаюсь узнать больше о том, как работает цепочка этих операторов и Observables.
Поэтому, после дальнейшего исследования функции 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
});
}
Я думаю, что я могу поменять второй оператор switchMap на flatMap, но я хочу, чтобы предыдущий (внешний) Observable был отменен.
take(1)
поэтомуObservable.interval
всегда выдает только один элемент, и тогда цепочка завершена.