Angular2 canActivate()调用asynchronous函数

我正在尝试使用Angular2路由器守卫来限制对我的应用程序中的一些页面的访问。 我正在使用Firebase身份validation。 为了检查用户是否使用Firebaselogin,我必须使用callback呼叫FirebaseAuth对象上的.subscribe() 。 这是警卫的代码:

 import { CanActivate, Router, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router'; import { AngularFireAuth } from "angularfire2/angularfire2"; import { Injectable } from "@angular/core"; import { Observable } from "rxjs/Rx"; @Injectable() export class AuthGuard implements CanActivate { constructor(private auth: AngularFireAuth, private router: Router) {} canActivate(route:ActivatedRouteSnapshot, state:RouterStateSnapshot):Observable<boolean>|boolean { this.auth.subscribe((auth) => { if (auth) { console.log('authenticated'); return true; } console.log('not authenticated'); this.router.navigateByUrl('/login'); return false; }); } } 

导航到具有警戒的页面时,无论是经过authenticated还是not authenticated都会打印到控制台(经过一段时间,等待来自Firebase的响应)。 但是,导航从来没有完成。 另外,如果我没有login,我被redirect到/login路线。 所以,我遇到的问题是return true不显示请求的页面给用户。 我假设这是因为我正在使用callback,但我无法弄清楚如何做到这一点,否则。 有什么想法吗?

canActivate需要返回一个完成的Observable

 @Injectable() export class AuthGuard implements CanActivate { constructor(private auth: AngularFireAuth, private router: Router) {} canActivate(route:ActivatedRouteSnapshot, state:RouterStateSnapshot):Observable<boolean>|boolean { return this.auth.map((auth) => { if (auth) { console.log('authenticated'); return true; } console.log('not authenticated'); this.router.navigateByUrl('/login'); return false; }).first(); // this might not be necessary - ensure `first` is imported if you use it } } 

有一个return缺less,我使用map()而不是subscribe()因为subscribe()返回一个Subscription不是一个Observable

canActivate可以返回一个parsingbooleanPromise

您可以使用Observable来处理asynchronous逻辑部分。 这里是我testing的代码例如:

 import { Injectable } from '@angular/core'; import { CanActivate } from '@angular/router'; import { Observable } from 'rxjs/Observable'; import { DetailService } from './detail.service'; @Injectable() export class DetailGuard implements CanActivate { constructor( private detailService: DetailService ) {} public canActivate(): boolean|Observable<boolean> { if (this.detailService.tempData) { return true; } else { console.log('loading...'); return new Observable<boolean>((observer) => { setTimeout(() => { console.log('done!'); this.detailService.tempData = [1, 2, 3]; observer.next(true); observer.complete(); }, 1000 * 5); }); } } }