canActivate doesn't respond upon subscription

2019-07-08 11:10发布

问题:

I'm using AngularFire2. This is how I approached my AuthGuard service:

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
    this.af.auth.subscribe((auth) =>  {
      if(auth == null) {
        this.router.navigate(['/login']);
        this.allowed = false;
      } else {
        this.allowed = true;
      }
    })
    return this.allowed;
  }

The above code works, except when I visit a guarded page directly (i enter URL in browser), it doesn't load the respective component after the subscription resolves to true.

In angular 1, guarding the route was ensuring something resolves first before the route even loads.

It appears in angular 2, the route loads (whether true or false, and doesn't wait for any response from the wire), therefore by the time the subscription value returns as true, I have to go to another route, then come back before it works.

What is the proper way to guard my route to be responsive in Angular 2?

回答1:

In your code return this.allowed; is executed before the callback function passed to this.af.auth.subscribe(...) is executed.

It should be like

  import 'rxjs/add/operator/map';
  import 'rxjs/add/operator/first';
  import { Observable } from 'rxjs/Observable';


  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
    return this.af.auth.map((auth) =>  {
      if(auth == null) {
        this.router.navigate(['/login']);
        return false;
      } else {
        return true;
      }
    }).first()
  }


回答2:

If you came looking for Angular 4 with angularfire 4, this how I adjusted Gunter's answer:

  canActivate(route: ActivatedRouteSnapshot):Observable<boolean>{
    return this.af.authState.map((user)=>{
      if(user != null){
        return true;
      }else{
        this._store.dispatch(new LayoutOpenLoginAction());
        return false;
      }
    }).first();
  }