我是ngrx的新手,我希望有人能和kind可亲并帮助我,因为我阅读了很多有关此问题的主题,而我仍然持相同观点。我正在测试@ngrx/effects
,我只想在应用程序启动时返回一个简单的用户角色数组(只是为了了解当前的工作方式)。当我在下面使用此代码时:
...
...
switchMap(() => this.roleService.getAllRoles().pipe(
map(roles => {
return new AllRolesLoaded({ roles });
}),
catchError((error) => of(new ErrorLoadRole(error)))
)),
// I got infinite loop
我有一个无限循环。通过对堆栈流的研究,我发现我必须使用.tap()
而不是.map()
。但是当我使用.tap()
:
...
...
switchMap(() => this.roleService.getAllRoles().pipe(
tap(roles => {
return new AllRolesLoaded({ roles });
}),
catchError((error) => of(new ErrorLoadRole(error)))
)),
// I got this:
// core.js:6014 ERROR Error: Effect "RoleEffects.loadRoles$" dispatched an invalid action: ...
// core.js:6014 ERROR TypeError: Actions must have a type property
对于无效操作,我尝试:-Effect dispatched an invalid action:-具有装饰器@Effect
(ngrx 8.0.1)的版本,版本createEffect()
(ngrx 8.3.0)。-swithMap()
mergeMap()
exhaustMap()
等...并且我得到了sama结果。
这里有完整的代码,也许您可以了解这里发生的事情。
// #actions/role.actions.ts
// ngrx version 8.0.1
export enum RoleActionTypes {
RequestLoadRoles = '[Role] Request Load data Roles',
AllRolesLoaded = '[Roles API] All Roles Loaded',
ErrorLoadRole = '[Roles API] Error load roles',
}
export class RequestLoadRoles implements Action {
readonly type = RoleActionTypes.RequestLoadRoles;
}
export class AllRolesLoaded implements Action {
readonly type = RoleActionTypes.AllRolesLoaded;
constructor(public payload: { roles: Role[] }) {}
}
export class ErrorLoadRole {
readonly type = RoleActionTypes.ErrorLoadRole;
constructor(public payload: HttpErrorResponse) {}
}
// ngrx version 8.3.0 but i cannot handle it yet
// export const RequestLoadRoles = createAction('[Role] Request Load data Roles');
// export const AllRolesLoaded = createAction('[Roles API] All Roles Loaded', props<{ role: Role[] }>());
export type RoleActions =
| RequestLoadRoles
| AllRolesLoaded
| ErrorLoadRole
;
// #effects/role.effect.ts
@Injectable()
export class RoleEffects {
// ngrx version 8.0.1
@Effect()
loadRoles$ = this.actions$.pipe(
ofType<RequestLoadRoles>(RoleActionTypes.RequestLoadRoles),
withLatestFrom(this.store.pipe(select(roles => roles.rolesLoaded))),
filter(([action, loaded]) => !loaded),
switchMap(() => this.roleService.getAllRoles().pipe(
tap(roles => { // with .tap() i got the invalid dispatched action, i dont know why, and .map() give my an infinite loop
return new AllRolesLoaded({ roles });
}),
catchError((error) => of(new ErrorLoadRole(error)))
)),
);
// ngrx version 8.3.0 but i cannot handle it yet
// loadRoles$ = createEffect(() => this.actions$.pipe(
// ofType('[Roles API] All Roles Loaded'),
// mergeMap(() => this.roleService.getAllRoles()
// .pipe(
// map(roles => ({ type: '[Roles API] All Roles Loaded', payload: roles })),
// catchError(() => EMPTY)
// ))
// )
// );
@Effect()
init$: Observable<RoleActions> = defer(() => {
return of(new RequestLoadRoles());
});
constructor(private actions$: Actions, private store: Store<RolesStateEntity>, private roleService: RoleService) {}
}
这里是控制台的全部错误:
core.js:6014 ERROR Error: Effect "RoleEffects.loadRoles$" dispatched an invalid action: [{"name":"ADMIN","permissions":["fullAccessUserManagement","canDeleteUserManagement","canUpdateUserManagement","canReadUserManagement"]},{"name":"MODERATOR","permissions":["canDeleteUserManagement","canUpdateUserManagement","canReadUserManagement"]},{"name":"USER","permissions":["canReadUserManagement"]},{"name":"GUEST","permissions":[]}]
at reportInvalidActions (effects.js:338)
at MapSubscriber.project (effects.js:428)
at MapSubscriber._next (map.js:29)
at MapSubscriber.next (Subscriber.js:49)
at ExhaustMapSubscriber.notifyNext (exhaustMap.js:60)
at InnerSubscriber._next (InnerSubscriber.js:11)
at InnerSubscriber.next (Subscriber.js:49)
at MergeMapSubscriber.notifyNext (mergeMap.js:69)
at InnerSubscriber._next (InnerSubscriber.js:11)
at InnerSubscriber.next (Subscriber.js:49)
...
Show 139 more frames
core.js:6014 ERROR TypeError: Actions must have a type property
at ActionsSubject.next (store.js:168)
at Store.next (store.js:709)
at SafeSubscriber.__tryOrUnsub (Subscriber.js:183)
at SafeSubscriber.next (Subscriber.js:122)
at Subscriber._next (Subscriber.js:72)
at Subscriber.next (Subscriber.js:49)
at MergeMapSubscriber.notifyNext (mergeMap.js:69)
at InnerSubscriber._next (InnerSubscriber.js:11)
at InnerSubscriber.next (Subscriber.js:49)
at Notification.observe (Notification.js:20)
[我在这里再次说,我得到了数据,但是我也得到了这个错误(当我使用.tap()
时)。另一个错误是无限循环(.map()
)。
如果您能抽出宝贵的时间阅读我的话,我先谢谢您,感谢您的帮助,因为此时此刻我正处于黑洞中。
您应该使用map
而不是tap
。tap
不返回值,因此这意味着您将把服务的结果分派回导致无效操作错误的商店。使用map
,您可以将服务响应转换为有效的NgRx操作。
您正在显示的代码是有效的,所以我想可能是其他原因导致了无限循环。
switchMap(() => this.roleService.getAllRoles().pipe(
map(roles => {
return new AllRolesLoaded({ roles });
}),
catchError((error) => of(new ErrorLoadRole(error)))
)),