NGRX - 对具有不同负载的 catchError 效果的分派操作

NGRX - dispatch action on catchError effect with different payload

我需要调用一个可以 return 错误、警告或成功的 API。

如果它 returns 警告,用户必须能够接受警告,我应该发送相同的有效负载 + acceptWarning: true。

我需要显示一个离子模式并等待用户的响应,看他是否接受或取消警告。

实现该目标的最佳方法是什么?

现在我有这样的东西:

  @Effect()
  public Assign$ = this.actions$.pipe(
    ofType(myActions.Assign),
    map(action => action.payload),
    exhaustMap(assignment =>
      this.assignService.assign(assignment).pipe(
        switchMap(() => {
          this.errorService.showPositiveToast(' Assigned Successfully');
          return [
            new LoadAssignments(),
            new LoadOtherData()
          ];
        }),
        catchError(error =>
          from(this.openErrorModal(error)).pipe(
            switchMap(({ data = '' }) => {
              if (data === 'Accept') {
                return of(new Assign({ ...assignment, acceptWarning: true }));
              }

              return of(new AssignShipmentFailure());
            })
          )
        )
      )
    )
  );


async openErrorModal(response: any) {
    const errorModal = await this.modalCtrl.create({
      component: ErrorValidationPopup,
      componentProps: {
        response: response,
      },
    });
    await errorModal.present();
    return errorModal.onDidDismiss();
  }

但它不会再次触发分配操作。感谢您的帮助

如果效果的可观察对象(或任何 Observable)发生任何错误,则其流不会发出任何值并立即出错。报错后没有完成,Effect会停止工作

为了在发生任何错误时保持 Effect 正常工作,您必须 swichMap 而不是 exhaustMap,并在 switchMap 的内部可观察对象中处理错误,所以主要的 Observable 不会受到影响。

Why use switchMap?

The main difference between switchMap and other flattening operators is the cancelling effect. On each emission the previous inner observable (the result of the function you supplied) is cancelled and the new observable is subscribed. You can remember this by the phrase switch to a new observable

您可以尝试以下操作:

@Effect()
public Assign$ = this.actions$.pipe(
  ofType(myActions.Assign),
  map(action => action.payload),
  switchMap(assignment =>
    this.assignService.assign(assignment).pipe(
      switchMap(() => {
        this.errorService.showPositiveToast('Assigned Successfully');
        return [
          new LoadAssignments(),
          new LoadOtherData()
        ];
      }),
      catchError(error =>
        from(this.openErrorModal(error)).pipe(
          map(({ data = '' }) => {
            if (data === 'Accept') {
              return new Assign({ ...assignment, acceptWarning: true });
            }

            return new AssignShipmentFailure();
          })
        )
      )
    )
  )
);