这个问题在某种程度上与这些问题有关1,2,但它们没有以可以帮助我的方式解决javascript中的同步可观察对象问题。
我目前处于角度4或角度,我有一条受保护的路线等待两名警卫解决。其中两个按预期返回true,但第二个需要太长时间才能在canActivate方法完成后得到答案。示例代码如下。我该怎么做才能让我的第二个后卫同步解决?
我是新手这个javascript和observables异步的做事方式!对不起,如果这个问题很愚蠢。
首先是authGuard:
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot):
boolean {
if(this.cookieService.check('token'))return true;
console.log(true); //For demostration purpose
}
第二个authGuard:
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot):
boolean {
this.roleService.checkRole('admin') // this service take some time
.subscribe(
response=>{
//Simple logic checking the response.
console.log(true);
return true;
},
error=>{
//some logic with the error
console.log(false);
return false;
}
)
console.log('End of authguard method');
}
roleService:
checkRole(role:string):
boolean {
return this.http.post(Url, body,requestOptions)
.map(this.processData)
.catch(this.handleError);
}
4.Console显示:
true // from authGuard 1
"End of authguard method" // from authGuard 2
true // from authGuard 2
路由器无法导航到所需的路由,因为第二个真的来得太晚了。我也在订阅之前尝试了first()
运算符,并且第一个运算符不等待role.Service中的observable来解析。
答案 0 :(得分:1)
CanActivate
的界面是
interface CanActivate {
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean>|Promise<boolean>|boolean
}
这意味着除了原始布尔值之外,它还将接受Promise
或Observable
的返回类型。您面临的问题是您正在尝试将Observable视为布尔值,而不是它。你应该重构你的第二个authGuard:
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean> {
return this.roleService
.checkRole('admin') // this service take some time
// Any success value is mapped to true
.mapTo(true)
// Any error will log and return false
.catch(e => {
console.log('Encountered an error checking role', e);
return Observable.of(false);
})
// This logs when this *actually* completes
.finally(() => console.log('End of authguard method'));
}
我们之所以需要这样做是因为作为一般模式,我们不知道Observable
何时会发出,我们只知道我们想要做什么。我们实际上正在返回一个将完成最终的工作流程,而不是尝试分配单个值。