如何在Ngrx的Angular Guard中使用CombineLatest



我正试图等待几个状态片成为我的保护区中的true

我试过了:

canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean> | Promise<boolean> | boolean {
return combineLatest([
this.store.select(
fromStore.selectProductsLoaded
),
this.store.select(fromStore.selectArticlesLoaded),
]).pipe(
map(([a, b]) => ({ a, b })),
filter(({ a, b}) =>  a && b),
first()
);
}

我需要这两个数据是true,所以我想使用combineLatest,但遇到了这个错误:Type 'Observable<{ a: boolean; b: boolean; }>' is not assignable to type 'Observable<boolean>'

相比之下,这种方法有效:

route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean> | Promise<boolean> | boolean {
return  this.store
.select(fromStore.selectProductsLoaded)
.pipe(
filter((loaded) => loaded),
take(1)
);
}

当您最终对来自商店的数据使用combineLatest时,IMO您可以将其视为危险信号或代码气味。

如果您想组合来自存储的一些数据,请使用选择器。主要区别在于,combineLatest只需要发射一次可观测到的,而不是至少发射两次(这将等待两者发射(。

它可能看起来如下:

const canActivateNameOfYourRoute = createSelector(
fromStore.selectProductsLoaded,
fromStore.selectArticlesLoaded,
(productsLoaded, articlesLoaded) => productsLoaded && articlesLoaded
);
class YourGuard {
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean> | Promise<boolean> | boolean {
return this.store.select(canActivateNameOfYourRoute).pipe(
filter(Boolean),
first()
);
}
}

之所以会出现此错误,是因为使用combineLatest可以传递一个可观测值数组,然后将其映射到结构为{a:boolean,b:boolean}的对象。

我想您希望基于这两个输入返回一个布尔值。

因此一个可能的解决方案是

.pipe(
map(([a, b]) => ({ a, b })),
filter(({ a, b}) =>  a && b),
map(values => {
// both a and b are true
if(values.a && values.b){
return true;
} else {
return false;
}
}),
first()
);

最新更新