在获取数据w / subscribe之后我发送动作时的无限循环

问题描述 投票:3回答:1

我是角度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 => {});
  }
angular6 ngrx-store rxjs6
1个回答
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)。

© www.soinside.com 2019 - 2024. All rights reserved.