我是angular 6和ngrx存储中的新手。我尝试从存储中获取数据订阅后调度操作,但它会导致无限循环并导致浏览器崩溃?我错了。我使用rxjs的do / tap运算符找到了一些解决方案,但仍然无法正常工作。例如,当我使用{{(feedState | async).loading}}时,它总是返回undefined。
我的组件:
ngOnInit() {
this.store.dispatch(new FeedActions.GetFeedCategories());
this.feedSubscription = this.store
.pipe(
select('feed'),
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 => {});
}
答案 0 :(得分:3)
select运算符将创建一个observable,每次“ feed”的状态更新时都会发出该观测值。这将在您执行FeedActions.GetFeedCategories()
时第一次触发,但是在将FeedActions.GetFeedItems(...)
的结果添加到状态时也会再次触发,这将导致再次执行FeedActions.GetFeedItmes(...)
,并且一次又一次...
简单的解决方案是在管道中添加take(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)。