Короче говоря:
Самый простой способ справиться с такими ситуациями - использовать оператор switchMap. Это отменяет внутреннюю подписку, как только появляется новое событие.
Одна реализация будет:
class MainComponent {
products: any[];
private _filters$ = new Subject();
constructor(private dataService: DataService_, private filtersService: FiltersService) {
}
ngOnInit() {
this.setProducts()
}
setProducts() {
this._filters$
.switchMap((filters)=> this.dataService.getProducts(filters)) // or .let(switchMap...) if you are using rxjs >5.5
.subscribe(products => this.products = products);
}
onFiltersChange() {
this._filters$.next(this.filtersService.filters);
}
}
Длинная история:
Что здесь происходит:
Когда вы меняете фильтр, срабатывает onFilterChange. Затем вы отправляете последние фильтры (внутри this.filtersService.filters) через объект $ _filters (тема почти идентична EventEmitter).
Время назад во время инициализации компонента метод ngOnInit вызвал setProducts, который подписался на тему _filters $ для будущих событий (на данный момент ничего не произошло). Когда событие поступает в _filters $, мы запускаем метод getProducts dataservice, передавая ему фильтры, содержащиеся в событии. Мы будем ждать на этой линии, пока не завершится http-вызов. Как только он завершится, результат http-вызова будет присвоен продуктам компонента.
Если пока мы ожидаем ответа http, снова запускается onFiltersChange, то в switchMap будет происходить новое событие, и оно отменяет предыдущий запрос http, чтобы он мог обработать новое событие.
Это очень мощный подход, поскольку при смене одного оператора вы можете легко изменить поведение вашего приложения. Например, изменение switchMap на concatMap заставит запрос ждать завершения предыдущего (будет происходить последовательно). Изменение его на flatMap будет иметь то же поведение, что и исходный код, который вы разместили (запросы http будут выполняться, как только фильтры изменятся, не влияя на предыдущие, порядок ответов не будет предсказуемым) и т. Д.