NgRx效果-内部catchError执行多次

时间:2019-07-05 19:37:30

标签: angular rxjs ngrx ngrx-effects

我有一个带有NgRx的Angulr应用程序,在我的特效之一中,我有一个意料之外的行为,事实证明这是预期的,但是我不知道如何解决它。

我的验证码是

@Effect()
detelete$ = this.actions$
  .pipe(
    ofType<fromActions.DeleteRequested>(fromActions.ActionTypes.DeleteRequested),
    map(action => action.payload.id),
    mergeMap(id =>
      combineLatest([
        of(id),
        this.rservice.deleteById(id)
          .pipe(
            catchError((err, caught$) => {
              this.store.dispatch(new fromActions.DeleteCancelled({id: id}));
              return caught$;
            })
          )
      ])
    ),
    map(([id, ]: [string, any]) => {
      return new fromActions.DeleteSuccess({id: id});
    }),
  );

我没有将catchErrormergeMap放在同一级别的原因是,我需要id作为fromActions.DeleteCancelled动作的有效负载。另外,我的服务仅返回布尔值,因此我使用combineLatest将其持久化到我的onSuccess map

我遇到的这个catchError正在执行多次。因此,多次分派我的错误操作。
我发现了

  

如果您返回此源,则可观察对象将有效地重新启动并重试

在这种情况下,source是我的caught$

如果我在cacthError内返回

  return of(new fromActions.DeleteCancelled({id: id}));

它仍将转到我的onSuccess map。我也许可以检查map中的第二个参数是否为Actionboolean类型,但我认为有适当的方法可以处理它,但我不知道。

StackBlitz (uncomment subscribe to see infinite loop)

谢谢。

1 个答案:

答案 0 :(得分:1)

您可以考虑采用这种方法。您的代码如下所示:

import { EMPTY, of, Observable } from 'rxjs';
...

@Effect()
delete$ = this.actions$.pipe(
  ofType<fromActions.DeleteRequested>(fromActions.ActionTypes.DeleteRequested),
  map(action => action.payload.id),
  switchMap((id) => this.rservice.deleteById(id).pipe(
    switchMap(result => {
      return result ? of(new fromActions.DeleteSuccess({id: id})) : EMPTY
    }),
    catchError(error => {
      return of(new fromActions.DeleteCancelled({id: id}))
    })
  )
)

如果您的服务正在返回true,那么将调度DeleteSuccess操作,否则将立即完成一个空的Observable。 由于EMPTY返回一个可观察值,因此您必须使用switchMap,还必须使用of返回一个动作DeleteSuccess的可观察对象。

如果发生错误,将派遣DeleteCancelled

另一种方法是使用@Effect({ dispatch: false }),并手动分派所有需要的操作。

希望这会有所帮助。