Ждать состояния в резольвере (ngrx)
Сейчас у меня есть резолвер, вызывающий стандартную службу и возвращающий Observable:
return this.someService.getData()
.map(data=> data.json())
Я хочу заменить его эффектами ngrx и сохранить. Когда решатель запускается, я хочу отправить requestAction, перехваченный эффектом, который отправляет http запрос. Как только данные возвращаются, я отправляю dataReceivedAction с данными в качестве полезной нагрузки.
В основном я хочу отправить действие в распознаватель и дождаться, пока новые данные появятся в хранилище. Я пытаюсь сделать это так:
return Observable.combineLatest(
Observable.of(
this.store.dispatch(new requestAction())
),
this.store.select(store => store.dataIWaitFor),
(dispatchedAction, dataArrived) => dataArrived
)
.skip(1)
это не работает, я имею в виду, что распознаватель не отображает компонент, но когда в конце каждого из этих возвращаемых Observables я добавляю
.do(data => console.log(data))
одни и те же данные регистрируются. Что я делаю не так?
2 ответа
Вы можете сделать что-то вроде этого
@Injectable()
export class SomeGuard implements CanActivate {
constructor(private store: Store<AppState>) {}
waitForDataToLoad(): Observable<Something> {
return this.store.select(state => state.something)
.filter(something => something && !something.empty);
}
canActivate(route: ActivatedRouteSnapshot): Observable<boolean> {
this.store.dispatch({type: LOAD_something});
return this.waitForDataToLoad()
.switchMap(() => {
return Observable.of(true);
});
}
}
}
Я попытался реализовать ваше решение в распознавателе вместо охранника, он хорошо заполняет мой магазин ngrx, но навигация не выполняется, я застрял на странице, откуда я вызываю маршрут с распознавателем. Также в магазине мы можем видеть данные и router-store/requested и router-store/navigation, но не router-store/navigated, ни router-store/cancel, например, когда охранник блокирует навигацию. Знаете, чего мне не хватает и почему ничего не происходит с навигацией? Я использовал преобразователь в своем маршруте следующим образом:
{
path: "params/users",
canActivate: [IsAdminGuard],
component: UsersComponent,
resolve: { usersLoaded: UsersResolver }
}
А вот и резольвер, почти как у вашей гвардии:
@Injectable()
export class UsersResolver implements Resolve<boolean> {
constructor(private store: Store<appState>) {}
resolve(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean> {
// API calls with ngrx effect
this.store.dispatch(usersActions.GET_USERS_TRY());
// Select users in store, switchMap(true) if array not empty
return this.store.pipe(
select(UsersSelectors.allUsers),
filter((allUsers: users[]) => allUsers.length > 0),
switchMap((allUsers: users[]) => return of(true))
);
}
}