Я новичок в ngrx, и я надеюсь, что кто-то может быть добрым и помочь мне, потому что я прочитал много тем об этой проблеме, и я все еще в том же духе. Я тестирую @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
(ngrx 8.0.1), версия createEffect()
(ngrx 8.3.0).
- swithMap()
mergeMap()
exhaustMap()
ect ... и у меня есть результат 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) {}
}
# reducer/role.reducer.ts
export const roleFeatureKey = 'role';
export interface RolesStateEntity {
rolesLoaded: boolean;
rolesLoading: boolean;
queryResult: Role[];
}
export const initialRolesState: RolesStateEntity = {
rolesLoaded: false,
rolesLoading: false,
queryResult: []
};
export function roleReducer(state = initialRolesState, action: RoleActions): RolesStateEntity {
switch (action.type) {
case RoleActionTypes.AllRolesLoaded:
return {
...state,
queryResult: action.payload.roles,
rolesLoading: false,
rolesLoaded: true,
};
case RoleActionTypes.ErrorLoadRole:
return {
...state,
rolesLoading: false,
};
default:
return state;
}
}
# service/role.service.ts there is only 1 method
getAllRoles(): Observable<Role[]> {
return new Observable(observer => {
const array = [
{
name: 'ADMIN',
permissions: ['fullAccessUserManagement', 'canDeleteUserManagement', 'canUpdateUserManagement', 'canReadUserManagement'],
},
{
name: 'MODERATOR',
permissions: ['canDeleteUserManagement', 'canUpdateUserManagement', 'canReadUserManagement'],
},
{
name: 'USER',
permissions: ['canReadUserManagement'],
},
{
name: 'GUEST',
permissions: [],
},
]
observer.next(array);
});
}
Здесь полная ошибка консоли:
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()
).
Я заранее благодарю вас, если вы нашли время, чтобы прочитать это, и я буду признателен вам за помощь, потому что в этот момент я в черномдыра.
Моя фотография бесконечного цикла здесь