Как сделать вторичный HTTP-запрос на основе результатов первого - PullRequest
1 голос
/ 12 июня 2019

У меня есть два асинхронных запроса, которые я пытаюсь выполнить, второй по результатам первого.Я пытаюсь сделать это следующим образом:

  1. Прослушайте успех первого действия: actions.GetAllItems
  2. Выберите из магазина соответствующие предметы на основе идентификатора: this.store.select(selectors.getItemsById)
  3. Сопоставить возвращенные идентификаторы, чтобы я мог выполнить второй вызов для каждого элемента в массиве идентификаторов, возвращаемых при первом вызове
  4. Поместить результаты в хранилище примитивов, отобразить для просмотра.

То, что я сейчас имею, успешно положило его в мой редукционный магазин.Однако, поскольку это просто ваниль Array.map, он не возвращает наблюдаемого.Что означает, что наблюдаемое не сохраняется в this.details$, что означает, что оно не отображается в моем шаблоне с {{ details$ | async | json }}

Как я могу выполнить этот вторичный вызов XHR на основе результатов первого?


ngOnInit() {

  this.store.dispatch(new actions.GetAllItems())

  this.details$ = this.actions$.pipe(
    ofType(actions.types.GetAllItemsSuccess),
    mergeMap(() => {
      return this.store.select(selectors.getItemsById); // filter to multiple items based on item ID
    }),
    map((items: models.IItemGeneralResponse[]) => {
      items.map(item => { // sync map does not seem like it belongs in rxjs
        this.store.dispatch(
          new actions.GetItemDetail(item.id)
        );
      });
    })
  );
}

1 Ответ

0 голосов
/ 12 июня 2019

Вы пытаетесь делать эффекты эффектов ngrx в вашем угловом компоненте. Используйте эффекты для обработки побочных эффектов (обращения к бэкэнду / извлечения данных из локального хранилища и т. Д.) И заставьте свой компонент отслеживать часть вашего состояния с помощью селектора. Подведем итоги вот так -

  1. Ваш компонент [или ваш охранник или распознаватель] просто отправит действие в магазин.
  2. Если вы установите редуктор для этого действия, тогда ваш редуктор будет вызван первым, в противном случае он перейдет к шагу 3
  3. В результате вы наблюдаете за отправленным действием. Ваш эффект совершит первый вызов, а затем по ответу на первый вызов произведет второй вызов, а затем обновит состояние в вашем хранилище [или части состояния], которое отслеживается вашим компонентом, путем отправки соответствующие действия в магазине.

Это типичный рабочий процесс [Может отличаться в зависимости от потребностей приложения, но основная идея остается неизменной]. Итак, придерживаясь основной идеи, давайте изменим ваш код следующим образом -

В вашем компоненте

sliceOfState$: Observable<any>; //change the type of observabe as per your app

  ngOnInit() {

    this.store.dispatch(new actions.GetAllItems())

    //this observable will be used to render your data on UI
    //you can use various rxjs operators to transform your data before shoing to UI
    this.sliceOfState$ = this.store.select(//your selector which gives you sliceOfState);
  }

Теперь в вашем действии -

@Effect()
  this.details$ = this.actions$.pipe(
    ofType(actions.types.GetAllItems),
    switchMap(() => {
      //here you call API which makes the call to backend which return allItems
      return this.yourServiceWhichGetAllItems.getAllItems();
    }),
    switchMap(allItems => {
      //now for each item you need to get its detail
      //so forkJoin all the observables which calls the backedn for each item
      const obs$ = allItems.map(item => this.yourServiceWhichGetDetails.getItemDetail(item));
      return forkJoin(obs$);
    })
    map(allItemsWithDetails => {
      //here you should call your action which will update the state in your store
      return new actions.SetAllItemsDetails(allItemsWithDetails);
    })    
  );

Я предоставил псевдокод, который даст вам представление о том, как достичь того, чего вы хотите. Для получения дополнительной информации, вы можете посетить официальный сайт ngrx - https://ngrx.io/guide/effects

...