在效果管道中组合选择器或检索动作参数

Combine selector or retrieve action parameter in effect pipeline

鉴于以下操作:

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

我想在 map 运算符中检索 clubId 操作参数以分派另一个操作:

@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 调用的结果...

我做错了什么?

您可以执行 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);
    }),
  );

顺便说一句,上面的代码可以直接return这两个动作。通过使用 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);
    }),
  );