我正在使用 @ngrx/store 开发 Angular 守卫来检查状态是否已经加载,我遇到了一个问题,如果我使用过滤器,canActivate
方法永远不会返回。
这是 GetCompanies 操作的示例效果:
return this.companiesService.getCompanies()
.pipe(
map(companies => new companiesActions.GetCompaniesSuccess(companies)),
catchError(error => Observable.of(new companiesActions.GetCompaniesFail(error)))
)
如果出现错误,我将调度 GetCompaniesFail 操作并将用户重定向到 /login
页面。没关系,有趣的部分是守卫。
@Injectable()
export class CompaniesGuard implements CanActivate {
constructor(
private store: Store<AppState>,
private router: Router
) {}
canActivate(): Observable<boolean> {
return this.checkStore()
.pipe(
switchMap(() => Observable.of(true)),
catchError(() => Observable.of(false))
);
}
checkStore(): Observable<boolean> {
return this.store.select(getCompaniesLoaded)
.pipe(
tap(loaded => {
if (!loaded) {
this.store.dispatch(new companiesActions.GetCompanies());
}
}),
filter(loaded => loaded),
take(1)
);
}
}
如果出现错误且加载不为假,canActivate
将不会返回任何内容,因为 checkStore
不执行任何操作。
如果我将 filter
更改为 map
它可以工作,但它只采用第一个值为 false
的值,即使数据将成功加载.
我错过了什么?我该如何处理那里的 HTTP 错误?有没有办法等待特定状态或在 checkStore
中抛出错误?
提前致谢!
最佳答案
如果您稍微分离职责,这似乎更容易处理。
无论如何,您都应该运行 checkStore
,而不是直接依赖于它的结果。相反,让商店通知您成功或失败并返回该结果。
请注意,ngrx 和 redux 鼓励单向数据流来简化应用逻辑。
商店属性 getCompaniesLoadedStatus
初始化为 initial,并在 内设置为success 或failed companiesActions.GetCompaniesSuccess
或 companiesActions.GetCompaniesFail
。
重试在服务中处理(更接近于获取)。
canActivate(): Observable<boolean> {
this.checkStore();
return this.store.select(getCompaniesLoadedStatus).pipe(
filter(status => status !== 'initial'),
map(status => status === 'success' ? true : false )
);
}
checkStore(): void {
this.store.select(getCompaniesLoadedStatus).pipe(
take(1) // so that unsubscribe is not needed
).subscribe(status =>
if (status === 'initial') {
this.store.dispatch(new companiesActions.GetCompanies());
}
);
}
关于angular - @ngrx/store pre-load guard catch 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48749478/