бесконечный цикл, когда я отправляю действие после получения данных с подпиской - PullRequest
0 голосов
/ 29 августа 2018

Я новичок в магазине Angular 6 и ngrx. Я пытаюсь отправить действие после того, как получаю данные из магазина, но это делает бесконечный цикл и сбой браузера? В чем я был не прав. Некоторое решение я нахожу с помощью do / tap оператора rxjs, но все еще не работает. И когда я использую {{(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 => {});
  }

1 Ответ

0 голосов
/ 29 августа 2018

Оператор выбора создаст наблюдаемый объект, который будет генерироваться каждый раз, когда обновляется состояние «подачи». Это срабатывает в первый раз, когда вы делаете 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) из предоставленного кода.

...