ngrx — Убедитесь, что все http-вызовы выполнены и сохранены в хранилище

#angular #store #ngrx

#angular #Магазин #ngrx

Вопрос:

Краткое изложение того, что я хочу

  • Вызовите api 1
  • Вызовите api 2
  • Подождите, пока эти данные не будут сохранены в store
  • Получите эти данные через на уровне effect

Описание

Что я хотел бы сделать, это просто подождать, пока некоторые действия не будут должным образом завершены и сохранены в хранилище. А затем запустите следующий.

Например,

 @Effect()
  getData1$: Observable<Action> = this.actions$.pipe(
    ofType(AuthActionTypes.getData1Action),
    switchMap(action => {  // Simply call an api and save data in the store by calling GetData1Success.
      this.httpClient.get(...)
      .pipe(
        map((result) => new GetData1Success(result))
      )
    })
  );
  
 @Effect()
  someEffect$: Observable<Action> = this.actions$.pipe(
    ofType(AuthActionTypes.UserLogIn),
    flatMap(_ => {  // get first data
      this.store.dispatch(new getData1());
      return of(_);
    }),
    flatMap(_ => {  // get second data
      this.store.dispatch(new getData2());
      return of(_);
    }),
    switchMap(action => { // run final action
      return [new finalAction()];
    }),
    catchError(() => of(new finalActionFailure()))
  );
  

И затем finalAction() выполняется,

 @Effect()
  finalEffect$: Observable<Action> = this.actions$.pipe(
    ofType(AuthActionTypes.FinalActionAction),
    switchMap(action => {
      this.store.pipe(select(fromData.data1)).subscribe(data1 => {this.data1 = data1});
      this.store.pipe(select(fromData.data2)).subscribe(data1 => {this.data2 = data2});

  // this.data1, this.data2 are empty...

      return [new finalAction()];
    })
  );
  

В someEffect$ оба getData1 и getData2 вызывают http-запрос и сохраняют, когда http-вызов успешно выполнен.

Проблема в том, что он не ждет, пока данные будут сохранены в хранилище. И просто finalAction выполняется.

Я понимаю почему, потому что flatMap подождите, пока getData1 это не будет сделано. Но нет GetData1Success .

В этом случае, как я могу правильно получить данные из хранилища в момент finalEffect$ ?

Спасибо.

РЕДАКТИРОВАТЬ 1: я уже пробовал использовать forkJoin . Но я понятия не имею, как перехватывать данные, когда они хранятся в хранилище.

Комментарии:

1. Это потому, что вы передаете http-запрос для вашей карты. Это должно быть перемещено в исходный канал

2. @Clouse24 Можете ли вы рассказать мне более подробно? Где находится «исходный канал»?

3. взгляните на оператор forkJoin

4. @timdeschryver Я действительно пробовал forkJoin (я часто использовал его до использования Ngrx). Однако я понятия не имею, как решить мою проблему с forkJoin. В моем случае я должен вызвать два действия. но как я могу использовать forkJoin и отслеживать, выполнены ли эти действия и сохранены ли данные в хранилище? Спасибо.

Ответ №1:

Я мог бы решить с помощью forkJoin . Но не уверен, что это чистый способ.

Дайте мне знать ваше мнение.

Итак, моим решением было изменение второго кода из приведенного выше.

 @Effect()
  someEffect$: Observable<Action> = this.actions$.pipe(
    ofType(AuthActionTypes.UserLogIn),
    switchMap(_ => {
      const data1 = this.httpClient.get(...);
      const data2 = this.httpClient.get(...);

      return forkJoin(data1, data2).pipe(
        tap(
         result => {
          // Here update data to the store.
          this.store.dispatch(GetData1Success(result[0]));
          this.store.dispatch(GetData2Success(result[1]));
         }

        )
      )

    }),
    switchMap(action => { // run final action
      return [new finalAction()];
    }),
    catchError(() => of(new finalActionFailure()))
  );
  

У меня уже есть вызванное действие, GetData1 которое получает data1, но я не смог использовать это действие в моем случае, потому что я понятия не имею, как уловить момент, когда data1 сохраняется в store .

И в конечном итоге использовал forkJoin с вызовом http-запроса вручную в switchMap .