Оператор выбора создаст наблюдаемый объект, который будет генерироваться каждый раз, когда обновляется состояние «подачи». Это срабатывает в первый раз, когда вы делаете FeedActions.GetFeedCategories()
, но также срабатывает снова, когда результат FeedActions.GetFeedItems(...)
добавляется в состояние, в результате чего FeedActions.GetFeedItmes(...)
будет выполняться снова, и снова, и снова .. .
Простое решение - добавить дубль (1) в трубу, чтобы вы получили только один выстрел карты и операторы касания:
ngOnInit() {
this.store.dispatch(new FeedActions.GetFeedCategories());
this.feedSubscription = this.store
.pipe(
select('feed'),
take(1),
map(data => {
this.feedState = data;
return data.categories;
}),
tap(data =>
this.store.dispatch(
new FeedActions.GetFeedItems({
cat_id: data[this.selectedIndex],
page: 0
})
)
)
)
.subscribe(data => {});
}
Однако, возможно, стоит подумать о разделении проблем - вы смешали работу по подготовке состояния с работой по выбору состояния для отображения. Лучшее решение может быть что-то вроде этого:
ngOnInit() {
this.store.dispatch(new FeedActions.GetFeedCategories());
this.store.pipe(
select('feed'),
take(1),
map(data => data.categories),
tap(data =>
this.store.dispatch(
new FeedActions.GetFeedItems({
cat_id: data[this.selectedIndex],
page: 0
})
)
)
)
.subscribe(() => {});
this.feedState = this.store.pipe(
select('feed')
);
}
... тогда в вашем шаблоне вы можете использовать {{feedState | async}}?.loading
или что угодно, как вам нужно.
Канал async
делает подписку для вас и ожидает, что будет доступно поле, а не поле необработанных данных. В вашем примере this.feedState должен иметь тип Observable<FeedState>
, но он выглядит как необработанный тип данных (например, FeedState вместо Observable) из предоставленного кода.