Angular RouteGuard实现权限跳转时报非void/any函数必须返回值如何解决
问题根因
- 报错的直接原因:
canActivate方法声明了非void/any的返回类型,但你没有在方法顶层返回任何值,你写的return语句全部属于subscribe的回调函数,不属于canActivate方法本身的返回值。 - 逻辑错误:Angular路由守卫原生支持接收
Observable/Promise类型的返回值,会自动订阅流等待异步结果,你手动调用subscribe之后拿到的是Subscription对象,既不符合守卫的返回类型要求,也无法让守卫感知到异步校验的结果。
修复方案
你不需要手动订阅service返回的Observable,只需要通过rxjs的map操作符对流的结果做转换,之后直接返回处理后的Observable即可,Angular会自动处理订阅和销毁逻辑,避免内存泄漏。
正确代码如下:
import { map } from 'rxjs/operators'; // 需先导入map操作符 @Injectable({ providedIn: 'root' }) export class PortfolioGuard implements CanActivate { constructor(private resourceAccessService: ResourceAccessService, private router: Router) { } canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree { const id = +route.paramMap.get('id'); // 返回处理后的Observable,不需要手动subscribe return this.resourceAccessService.checkUserAccessToPortfolio(id).pipe( map(hasAccess => { if (!hasAccess) { console.log('No access'); return this.router.parseUrl('/'); } console.log('access'); return true; }) ); } }
补充说明
你之前直接返回原始Observable<boolean>能运行的原因就是Angular自动订阅了这个流,用map做转换后只是把流的输出从单纯的布尔值,改成了布尔值或者UrlTree对象,既保留了异步校验的能力,也实现了自定义跳转的需求。
内容的提问来源于stack exchange,提问作者Christian Phillips
相关产品推荐
相关产品推荐

