我有一个带有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});
}),
);
我没有将catchError
与mergeMap
放在同一级别的原因是,我需要id
作为fromActions.DeleteCancelled
动作的有效负载。另外,我的服务仅返回布尔值,因此我使用combineLatest
将其持久化到我的onSuccess
map
。
我遇到的这个catchError
正在执行多次。因此,多次分派我的错误操作。
我发现了
如果您返回此源,则可观察对象将有效地重新启动并重试
在这种情况下,source
是我的caught$
。
如果我在cacthError
内返回
return of(new fromActions.DeleteCancelled({id: id}));
它仍将转到我的onSuccess map
。我也许可以检查map
中的第二个参数是否为Action
或boolean
类型,但我认为有适当的方法可以处理它,但我不知道。>
StackBlitz (uncomment subscribe
to see infinite loop)
谢谢。
答案 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 })
,并手动分派所有需要的操作。
希望这会有所帮助。