Объединить селектор или получить параметр действия в конвейере эффекта - PullRequest
1 голос
/ 03 мая 2020

Учитывая следующее действие:

export const UpsertChartMember = createAction(ClubDetailActionTypes.UPSERT_CHART_MEMBER, props<{ clubId: number, member: IChartMember}>());

Я бы хотел получить параметр действия clubId в операторе map для отправки другого действия:

@Effect({ dispatch: false })
  upsertChartMember = this.actions$.pipe(
    ofType(UpsertChartMember),
    mergeMap(action => {
      const member = action.member;
      return this.chartMemberDataService.update(member);
    }),
    map(member => {
      this.messageService.success(this.constService.SAVE_SUCCESS);
      this.clubDetailStore.dispatch(UpsertChartMemberSuccess({ member: member }));

      // retrieve action.clubId here?! O_o?
      // TODO: dispatch here another action based upon action clubId

    }),
    catchError((error) => {
      this.messageService.error(this.constService.SAVE_FAILURE);
      this.clubDetailStore.dispatch(UpsertClubChartFailure({ err: error }));
      return throwError(error);
    }),
  );

как альтернатива У меня уже есть в модуле хранилища возможностей clubId, доступный для выделенного селектора:

export const getCurrentClub$ = createSelector(getclubDetailState$, (state: ClubDetailState) => state.form);

, но я не понимаю, как объединить селектор и результат вызова ajax в моем действии ...

Что я делаю не так?

1 Ответ

1 голос
/ 03 мая 2020

Вы можете сделать switchMap, чтобы получить его из магазина, используя уже имеющийся селектор, и combineLatest, чтобы сохранить передачу информации member вперед и club, извлеченных из магазина:

@Effect({ dispatch: false })
  upsertChartMember = this.actions$.pipe(
    ofType(UpsertChartMember),
    mergeMap(action => {
      const member = action.member;
      return this.chartMemberDataService.update(member);
    }),
    switchMap(member => combineLatest([
      of(member),
      this.store.pipe(select(getCurrentClub$)),
    ])),
    map(([member,club]) => {
      this.messageService.success(this.constService.SAVE_SUCCESS);
      this.clubDetailStore.dispatch(UpsertChartMemberSuccess({ member: member }));

      // now you have your club to do whatever you want to
      console.log({club});

    }),
    catchError((error) => {
      this.messageService.error(this.constService.SAVE_FAILURE);
      this.clubDetailStore.dispatch(UpsertClubChartFailure({ err: error }));
      return throwError(error);
    }),
  );

Кстати, код выше может вернуть оба действия напрямую. Используя switchMap. Вместо карты вы можете использовать другую цепочку:

@Effect()
  upsertChartMember = this.actions$.pipe(
    ofType(UpsertChartMember),
    mergeMap(action => {
      const member = action.member;
      return this.chartMemberDataService.update(member);
    }),
    switchMap(member => combineLatest([
      of(member),
      this.store.pipe(select(getCurrentClub$)),
    ])),
    switchMap(([member, club]) => {
      this.messageService.success(this.constService.SAVE_SUCCESS);  
      return [
        UpsertChartMemberSuccess({ member: member }),
        PutYourOtherActionHere({club...})
      ];
    }),
    catchError((error) => {
      this.messageService.error(this.constService.SAVE_FAILURE);
      this.clubDetailStore.dispatch(UpsertClubChartFailure({ err: error }));
      return throwError(error);
    }),
  );

[Отредактировано автором вопроса]: Или, сохраняя большую часть кода в том виде, как он есть:

@Effect({ dispatch: false })
  upsertChartMember: any = this.actions$.pipe(
    ofType(UpsertChartMember),
    mergeMap(action => {
      const member = action.member;
      let obs: Observable<IChartMember>;
      if (member.id > 0) {
        obs = this.chartMemberDataService.update(member);
      } else {
        obs = this.chartMemberDataService.add(member);
      }
      return combineLatest(of(action), obs);
    }),
    map((args) => {
      this.messageService.success(this.constService.SAVE_SUCCESS);
      this.clubDetailStore.dispatch(UpsertChartMemberSuccess({ member: args[1] }));
      this.clubDetailStore.dispatch(GetClubOrganizationCharts({clubId: args[0].clubId}));
    }),
    catchError((error) => {
      this.messageService.error(this.constService.SAVE_FAILURE);
      this.clubDetailStore.dispatch(UpsertClubChartFailure({ err: error }));
      return throwError(error);
    }),
  );
...