Проверьте наличие элемента в списке загружаемых файлов в ngrx
Я пытаюсь построить последовательность команд RXJS в охране, чтобы достичь этого результата в простом приложении библиотеки (как в книгах):
- Проверить в магазине
- Если состояние не загружено, запустите действие
- После загрузки отфильтруйте данные, чтобы найти один конкретный элемент.
- Если найдете, разрешите доступ к странице, если нет, отправьте на 404
Некоторое время я боролся, и поиск в Интернете не дает ответа в соответствии с версией 6 Angular или стандартами... Что мне удалось сделать, это создать большую часть, если магазин загружен, прежде чем поразить охранника, но если ему нужно извлечь данные, он зацикливается бесконечно.
canActivate(route: ActivatedRouteSnapshot): Observable<boolean> {
return this.store.pipe(
select(state => state.books),
tap(state => {
if (!state.loaded) {
this.store.dispatch(new BooksActions.Load());
}
}),
filter(state => state.loaded),
take(1),
map(state => state.list.find(book => book.id === route.params['id'])),
map((book) => {
if(!!book) return true;
this.router.navigate(['/404']);
return false;
})
);
}
Большое спасибо!
1 ответ
Проблема в этом разделе:
select(state => state.books),
tap(state => {
if (!state.loaded) {
this.store.dispatch(new BooksActions.Load());
}
}),
Как только вы отправите действие Load, скорее всего, ваш редуктор установит загруженное свойство в false, повторно запустив начальный селектор, который снова инициирует отправку действия.
То, как я это вижу, что вам нужно сделать, это:
- Проверьте только один раз, если список загружен. Если это не так, отправьте действие. В противном случае NOOP.
- Как только предыдущий шаг будет завершен, дождитесь загрузки списка и проверьте один раз на наличие сущности.
Это может быть заархивировано через следующее:
canActivate(route: ActivatedRouteSnapshot): Observable<boolean>
{
return concat(this.loadIfRequired(), this.hasBookInStore(route.params['id'])).pipe(skip(1));
}
private loadIfRequired(): Observable<any>
{
return booksState$.pipe(
map(state => state.loaded),
take(1),
tap(loaded=> {
if (!loaded) {
this.store.dispatch(new BooksActions.Load());
}
}));
}
private hasBookInStore(id: string): Obsevable<boolean>
{
return this.booksState$.pipe(
first(state => state.loaded),
map(state => state.list.find(book => book.id === id)),
map((book) => {
if(!!book) return true;
this.router.navigate(['/404']);
return false;
})
);
}
private get booksState$(): Observable<BooksState>
{
return this.store.pipe(
select(state => state.books));
}
Позвольте мне знать, если это помогает.