我在一项服务中有一个观察员:
hasAccess$: Observable<boolean>;
这被分配在一个单独的组件中。它包含filter()
,并且永远不会发出false,而只会发出true。因此,如果它为假,则不会发出。
我需要在路由防护中使用它。所以我尝试了:
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean> {
return this.service.hasAccess$.pipe(
defaultIfEmpty(false),
tap(access => {
console.log({access}); // never logs
}),
first()
);
}
defaultIfEmpty()
来确保发出一个值tap()
记录是否发生了任何事情(没有发生)first()
是因为在守卫中返回的可观察物必须完整。我确保分配了this.service.hasAccess$
。如果不是这样,则会引发错误,因为您无法传送未定义的内容。没有错现在很奇怪的是,它发出了false:
return of().pipe(
defaultIfEmpty(false),
tap(access => {
console.log({access});
}),
first()
);
两者都通过管道传输到defaultIfEmpty(false)
。警卫队为什么不散发武器?
更新:感谢@martin指出defaultIfEmpty()
仅在完成时发出。我现在也意识到,first()
如果不发出任何东西,将无法完成它。我想我需要弄清楚当它什么都不发出时如何使其完成。
答案 0 :(得分:1)
您可以将startWith(false)
运算符添加到您的hasAccess$
可观察值中,这样它将始终发出一些信息:
hasAccess$: Observable<boolean> = this.someServiceCall().pipe(startWith(false));
或者您可以在canActivate()
方法中引入超时:
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean> {
return this.service.hasAccess$.pipe(
timeout(5000),
first(),
catchError(() => of(false))
);
}
如果我是你,如果hasAccess$
从商店或同步源获取值,则使用第一种方法;如果进行异步调用,则使用方法2。
答案 1 :(得分:0)
想出了一个解决方案:
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean> {
return this.service.hasAccess$.pipe(
merge(of(false)),
first()
);
}
hasAccess$
移出,false
合并,first()
,因此,如果hasAccess$
发出true,则采用它,否则,如果不发出任何东西,则防护措施为false。