Angular 5中CanActivate守卫未返回值问题求助(附代码)
解决Angular 5 CanActivate守卫未返回值的问题
我帮你排查了下代码,导航失败的核心原因是你的canActivate方法在处理异步HTTP请求时没有返回对应的Observable,导致守卫无法等待授权请求完成就结束了,自然没有返回值。另外还有个小问题:你用map的第二个参数处理错误是不对的,map只负责转换数据,错误处理得用catch操作符。
问题点拆解
- 未返回Observable:当你从
sessionStorage或localStorage拿到token后,调用this.userservice.returnauthorizetoken(token)发起HTTP请求,但只是调用了map操作符,没有把整个Observable链return出去,守卫根本不知道要等这个异步操作完成。 - 错误处理方式错误:
map操作符的第二个参数不是错误回调,旧版RxJS(Angular 5用的是RxJS 5)里需要用catch操作符来捕获HTTP请求的错误。
修正后的完整代码
import {Observable} from 'rxjs/Observable'; import 'rxjs/add/operator/map'; import 'rxjs/add/operator/catch'; // 新增catch操作符的导入 import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from '@angular/router'; import {Injectable} from '@angular/core'; import {UserAuthorizationService} from "../userauthorizationservice/userauthorizationservice"; @Injectable() export class ClientSuitsAdminSuperUserGuard implements CanActivate{ constructor(private userservice: UserAuthorizationService, private router: Router){} user ={ id: null, isclient: false, issuitsviewer: false, issuitsadministrator: false, issuitssuperuser: false, isvenueuser: false }; canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | boolean { let token = this.userservice.checklocalfortoken(); console.log('running the local check'); if(token == null){ console.log('running the session check'); token = this.userservice.checksessionfortoken(); if(token == null){ console.log('no session token nav to sign in return false'); this.router.navigate(['/signin']); return false; } console.log('got session token authorizing it'); // 这里要return整个Observable链 return this.userservice.returnauthorizetoken(token) .map( (req: any)=>{ this.user = req; console.log('this is the user object from the session auth'); console.log(this.user); if(this.user.isclient || this.user.issuitsadministrator || this.user.issuitssuperuser){ console.log('the user has permissions from the session'); return true; }else{ console.log('the user does not have permissions from the session'); this.router.navigate(['/401']); return false; } }) .catch( error => { // 用catch处理错误 console.log('error with the session authorization'); this.router.navigate(['/signin']); return Observable.of(false); // 返回一个false的Observable }); }else{ console.log('doing the local check'); // 同样要return这个Observable链 return this.userservice.returnauthorizetoken(token) .map( (req: any)=>{ this.user = req; console.log('got the user object from the local'); console.log(this.user); if(this.user.isclient || this.user.issuitsadministrator || this.user.issuitssuperuser){ console.log('user has permissions from the local'); return true; }else{ console.log('user does not have permissions from the local'); this.router.navigate(['/401']); return false; } }) .catch( error => { // 用catch处理错误 console.log('error from the local authorization'); this.router.navigate(['/signin']); return Observable.of(false); // 返回一个false的Observable }); } } }
关键修改说明
- 返回Observable:在两个异步处理分支里,都添加了
return,把HTTP请求的Observable返回给canActivate方法,这样守卫会等待异步操作完成,拿到返回的true/false后再决定是否允许导航。 - 错误处理替换为
catch:移除了map的第二个错误参数,改用catch操作符捕获HTTP错误,并且返回Observable.of(false)来确保守卫能拿到一个有效的布尔值Observable。 - 确保所有路径都有返回值:不管是同步的
return false,还是异步的return Observable<boolean>,所有分支都明确返回了守卫需要的值。
这样修改后,当你访问受保护路由时,守卫会正确等待授权请求完成,根据返回结果决定是否允许导航,也能正确处理请求错误的情况。
内容的提问来源于stack exchange,提问作者user9487981
相关产品推荐
相关产品推荐

