【问题标题】:add a parameter to a selector in effect将参数添加到有效的选择器
【发布时间】:2019-10-18 04:18:39
【问题描述】:

我有以下

  createMission$ = this.actions$.pipe(
    ofType<featureActions.CreateMissionRequest>(featureActions.ActionTypes.CreateMissionRequest),
    withLatestFrom(this.store$.select(MissionsStoreSelectors.getById(), {id : action.payload.routeId}))
    switchMap((action) =>
      this.dataService.createMission(action.payload.mission).pipe(
        map(response => new featureActions.CreateMissionSuccess({response, mission : action.payload.mission})),
        catchError((error: HttpErrorResponse) => {
          this.snackBar.open(this.translate.instant('ERROR.HTTP.GENERIC'), this.translate.instant('BUTTON.OK'), {duration: 2500});
          return of(new featureActions.CreateMissionFailed({error}));
        }),
      ),
    ),
  );

问题是,在 withLatestFrom 中,我想在选择器中使用来自操作的参数。我如何做到这一点?

    withLatestFrom(this.store$.select(MissionsStoreSelectors.getById(), {id : action.payload.routeId}))
    switchMap((action, valueFromLatest) =>

编辑:我试过了

  @Effect()
  createMission$ = this.actions$.pipe(
    ofType<featureActions.CreateMissionRequest>(featureActions.ActionTypes.AssignMissionRequest),
    withLatestFrom((action) => this.store$.select(MissionsStoreSelectors.getById(), {id : action.payload.routeId})),
    switchMap((mission, action) =>
      this.dataService.createMission(action.payload.mission).pipe(
        map(response => new featureActions.CreateMissionSuccess({response, mission : action.payload.mission})),
        catchError((error: HttpErrorResponse) => {
          this.snackBar.open(this.translate.instant('ERROR.HTTP.GENERIC'), this.translate.instant('BUTTON.OK'), {duration: 2500});
          return of(new featureActions.CreateMissionFailed({error}));
        }),
      ),
    ),
  );

但我在 action.payload 上有类型错误(action 变成了一个数字)似乎不起作用

【问题讨论】:

  • 不是你自己定义的选择器jsut方法吗?那么没有什么能阻止你向他们添加过滤器
  • 我知道,问题是我不知道如何从 switchmap 外部访问操作以进入 withLatestFrom
  • 尝试做这样的事情:(action)=&gt;withLatestFrom(this.store$.select(MissionsStoreSelectors.getById(), {id : action.payload.routeId})) 用调试器看看你得到了什么

标签: angular store ngrx


【解决方案1】:

您可以使用switchMapcombineLatest 来实现这一点,但我没有在您的代码中看到您想要使用选择器的结果(来自选择器的数据)。我假设原始操作 (CreateMissionRequest) 在其有效负载中有两个属性:routeIdmission。但这没有任何意义,因为您使用了选择器并且再也不会使用它的结果。但是您可以通过查看下面的技术来获得总体思路,然后做任何您想做的事情。

更新
createMission$ = this.actions$.pipe(
    ofType<featureActions.CreateMissionRequest>(featureActions.ActionTypes.CreateMissionRequest),
    // This is where you use the switchMap
    switchMap((action) =>
        // combineLatest here makes it possible to pass forward the results
        // from the selector and the original action if you need
        combineLatest([ 
          this.store$.pipe(select(MissionsStoreSelectors.getById(), {id : action.payload.routeId}),take(1)),
          of(action.payload.routeId),
        ])),
    switchMap(([mission,routeId]) =>
      this.dataService.createMission(mission).pipe(
        map(response => new featureActions.CreateMissionSuccess({response, mission})),
        catchError((error: HttpErrorResponse) => {
          this.snackBar.open(this.translate.instant('ERROR.HTTP.GENERIC'), this.translate.instant('BUTTON.OK'), {duration: 2500});
          return of(new featureActions.CreateMissionFailed({error}));
        }),
      ),
    ),
  );

事实上,如果你只是需要将一个 observable 转换为另一个,switchMap 可以为你完成这项工作,不需要combineLatest

createMission$ = this.actions$.pipe(
    ofType<featureActions.CreateMissionRequest>(featureActions.ActionTypes.CreateMissionRequest),
    switchMap((action) =>  
        this.store$.pipe(select(MissionsStoreSelectors.getById(), {id : action.payload.routeId}),take(1))),
    switchMap((mission) =>
      this.dataService.createMission(mission).pipe(
        map(response => new featureActions.CreateMissionSuccess({response, mission})),
        catchError((error: HttpErrorResponse) => {
          this.snackBar.open(this.translate.instant('ERROR.HTTP.GENERIC'), this.translate.instant('BUTTON.OK'), {duration: 2500});
          return of(new featureActions.CreateMissionFailed({error}));
        }),
      ),
    ),
  );

【讨论】:

  • 我没有在参数中传递任务,只是传递任务 ID,我想将商店中存在的任务发送到服务器。
  • 另外,它说 combineLatest 已被弃用,但会尝试实现这一点,谢谢
  • 您必须从rxjs 导入combineLatest,而不是从rxjs/operators。它没有被弃用,但您必须将数组作为参数传递,即使您只有一个参数。我忘记了后者。
  • 我试过你的例子,但是使用双 switchMap,每次我的任务被保存时,选择器再次触发,我陷入了无限循环。
  • 这很奇怪。 store$.pipe(...) 后面的 switchMap 应该取消选择器订阅。无论如何,我在store$.pipe(...) 中添加了take(1)。如果它仍在触发,则可能是代码的另一部分中的其他内容。
猜你喜欢
  • 1970-01-01
  • 2021-07-09
  • 1970-01-01
  • 2020-02-04
  • 1970-01-01
  • 2022-11-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多