I'm using ngrx / (store, effects) in Angular 6. I have the problem in the resolution of one of the routing variables by a resolver. Here the code and the explanation
Resolver
@Injectable()
export class HkSpecialitiesResolver implements Resolve<Speciality[]> {
constructor(
private store: Store<AppState>) {
}
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Speciality[]> {
return this.store
.pipe(
select(selectAllSpecialities),
tap(specialities => {
if (!specialities || specialities.length === 0) {
this.store.dispatch(new AllSpecialitiesRequested());
}
}),
filter((specialities: Speciality[]) => {
return specialities !== [];
}),
take(select(selectAllSpecialities).length)
);
}
}
Effects
@Injectable()
export class HkSpecialitiesEffects {
@Effect()
loadAllSpecilities$ = this.actions$
.pipe(
ofType<AllSpecialitiesRequested>(SpecialityActionTypes.AllSpecialitiesRequested),
withLatestFrom(this.store.pipe(select(allSpecialitiesLoaded))),
filter(([action, allSpecialitiesLoaded]) => {
console.log('loadAllSpecilities$ - ', [action, allSpecialitiesLoaded]);
return !allSpecialitiesLoaded;
}),
mergeMap((o) => {
console.log('loadAllSpecilities$ - mergeMap', o);
return this.specialityService.findAll();
}),
map((specialities: Speciality[]) => {
console.log('loadAllCourses$ - map', specialities);
return new AllSpecialitiesLoaded({specialities});
})
);
constructor(private actions$: Actions, private specialityService: HkSpecialitiesService,
private store: Store<AppState>) {
}
}
Reducer
export interface SpecialitiesState extends EntityState<Speciality> {
allSpecialitiesLoaded: boolean;
}
export const adapter: EntityAdapter<Speciality> =
createEntityAdapter<Speciality>({
selectId: (speciality: Speciality) => {
return (speciality !== undefined) ? speciality.uuid : undefined;
}
});
export const initialSpecialitiesState: SpecialitiesState = adapter.getInitialState({
allSpecialitiesLoaded: false
});
export function specialityReducer(state = initialSpecialitiesState, action: SpecialityActions): SpecialitiesState {
switch (action.type) {
case SpecialityActionTypes.SpecialityLoaded:
return adapter.addOne(action.payload.speciality, state);
case SpecialityActionTypes.AllSpecialitiesLoaded:
return adapter.addAll(action.payload.specialities, {...state, allSpecialitiesLoaded: true});
case SpecialityActionTypes.SpecialitySaved:
return adapter.updateOne(action.payload.speciality, state);
default: {
return state;
}
}
}
export const {
selectAll,
selectEntities,
selectIds,
selectTotal
} = adapter.getSelectors();
Service
@Injectable()
export class HkSpecialitiesService {
constructor(private http: HttpClient) {
}
findAll(): Observable<Speciality[]> {
const vm = this;
// it works with these lines
/*return Observable.create((observer) => {
observer.next([{id: 'a', uuid: 'a', name: 'Psychology', description: 'Psychology'}]);
});*/
// Not works with this line
return vm.http.get<Speciality[]>('/api/specialities').pipe(map((specialities) => specialities));
}
}
The problem is that just as the code is, the resolves specialities variable is resolved as empty ([]), in the component I get it empty, an empty array. But if in the service, I change the http invocation, for the line that is commented, the resolution of the variable in the resolver takes the only correct value that I am returning.
The "Resolver" is resolved before the effect ends, when in the service it invokes the get of the http.
What I do not understand is that the commented line (with which everything works) returns an observable with the same content as that of the http invocation.
Any suggestions?