我正在使用@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)
);
}
}
如果出现错误并且加载不是false,则canActivate
不会返回任何内容,因为checkStore
什么都不做。
如果我将filter
更改为map
它可以正常工作,但即使数据成功加载,它也只需要false
的第一个值。
我错过了什么?我该如何处理HTTP错误?有没有办法等待某个状态或在checkStore
内抛出错误?
提前感谢!
答案 0 :(得分:0)
如果你将职责分开一点,这似乎更容易处理。
您应该运行checkStore
,而不是直接依赖它的结果。相反,让商店告知您成功或失败并返回结果。
请注意,ngrx和redux鼓励 单向数据流 来简化应用逻辑。
商店属性getCompaniesLoadedStatus
初始化为初始,并在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());
}
);
}