NgRx 效果 - 内部 catchError 执行多次
NgRx Effect - inner catchError executes multiple times
我有一个带有 NgRx 的 Angular 应用程序,在我的一个效果中我有一个非预期的行为,结果证明是预期的,但我不知道如何修复它。
我的压缩代码是
@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});
}),
);
我的 catchError
没有和我的 mergeMap
处于同一级别的原因是我需要我的 id
作为我的 fromActions.DeleteCancelled
操作的有效载荷。另外,我的服务只有 return 一个布尔值,所以我使用 combineLatest
将它持久化到我的 onSuccess
map
.
我遇到的是 catchError
执行了多次。因此,多次调度我的错误操作。
我发现
If you return this source, the observable will effectively restart all over again and retry
在这种情况下,source
是我的 caught$
。
如果,在我的cacthError
里面我return
return of(new fromActions.DeleteCancelled({id: id}));
它仍然会转到我的 onSuccess map
。我也许可以检查 map
中的第二个参数是否是 os 类型 Action
或 boolean
,但我认为有一种正确的方法来处理它,但我不知道它。
StackBlitz (uncomment subscribe
to see infinite loop)
谢谢。
你可以考虑这种方法。您的代码可能如下所示:
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}))
})
)
)
如果您的服务正在 returning true
,那么会调度 DeleteSuccess
操作,否则会立即完成一个空的可观察对象。
因为 EMPTY
return 是一个可观察的,所以你必须使用 switchMap
,并且 of
到 return 一个可观察的动作 DeleteSuccess
。
如有错误,DeleteCancelled
被派遣。
另一种方法是使用 @Effect({ dispatch: false })
,并手动调度所有需要的操作。
希望对您有所帮助。
我有一个带有 NgRx 的 Angular 应用程序,在我的一个效果中我有一个非预期的行为,结果证明是预期的,但我不知道如何修复它。
我的压缩代码是
@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});
}),
);
我的 catchError
没有和我的 mergeMap
处于同一级别的原因是我需要我的 id
作为我的 fromActions.DeleteCancelled
操作的有效载荷。另外,我的服务只有 return 一个布尔值,所以我使用 combineLatest
将它持久化到我的 onSuccess
map
.
我遇到的是 catchError
执行了多次。因此,多次调度我的错误操作。
我发现
If you return this source, the observable will effectively restart all over again and retry
在这种情况下,source
是我的 caught$
。
如果,在我的cacthError
里面我return
return of(new fromActions.DeleteCancelled({id: id}));
它仍然会转到我的 onSuccess map
。我也许可以检查 map
中的第二个参数是否是 os 类型 Action
或 boolean
,但我认为有一种正确的方法来处理它,但我不知道它。
StackBlitz (uncomment subscribe
to see infinite loop)
谢谢。
你可以考虑这种方法。您的代码可能如下所示:
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}))
})
)
)
如果您的服务正在 returning true
,那么会调度 DeleteSuccess
操作,否则会立即完成一个空的可观察对象。
因为 EMPTY
return 是一个可观察的,所以你必须使用 switchMap
,并且 of
到 return 一个可观察的动作 DeleteSuccess
。
如有错误,DeleteCancelled
被派遣。
另一种方法是使用 @Effect({ dispatch: false })
,并手动调度所有需要的操作。
希望对您有所帮助。