2016-07-17 5 views
23

Ich versuche Angular2 Router Wächter zu verwenden, um den Zugriff auf einige Seiten in meiner App einzuschränken. Ich verwende Firebase-Authentifizierung. Um zu überprüfen, ob ein Benutzer bei Firebase angemeldet ist, muss ich .subscribe() auf dem FirebaseAuth Objekt mit einem Rückruf aufrufen. Dies ist der Code für die Wache:Angular2 canActivate() ruft asynchrone Funktion auf

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; 
     }); 
    } 
} 

Wenn ein Navigieren Sie zu einer Seite, die die Wache auf sie hat, entweder authenticated oder not authenticated auf der Konsole ausgegeben wird (nach einer gewissen Verzögerung auf die Antwort von Feuerbasis zu warten). Die Navigation wird jedoch nie abgeschlossen. Auch wenn ich nicht eingeloggt bin, werde ich auf die Route /login umgeleitet. Also, das Problem, das ich habe ist return true zeigt nicht die angeforderte Seite für den Benutzer. Ich nehme an, das ist, weil ich einen Rückruf verwende, aber ich bin nicht in der Lage, herauszufinden, wie es sonst geht. Irgendwelche Gedanken?

+0

importieren Observable wie folgt -> importieren {Observable} von 'rxjs/Observable'; –

Antwort

50

canActivate Bedürfnisse ein Observable zurückzuversetzen ergänzt:

eine Promise zurückkehren können
@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 
    } 
} 

Es gibt eine return fehlt und ich verwende map() statt subscribe() weil subscribe() gibt ein Subscription kein Observable

+0

können Sie zeigen, wie diese Klasse in anderen Komponenten verwendet wird? –

+0

Nicht sicher, was du meinst. Sie verwenden dies mit Routen, nicht mit Komponenten. Siehe https://angular.io/docs/ts/latest/guide/router.html#!#guards –

+0

Das Observable wird in meinem Fall nicht ausgeführt. Ich sehe keine Konsolenausgabe. Wenn ich jedoch boolesche Bedingungen (wie in der Dokumentation) zurückgebe, wird die Konsole protokolliert. Ist das .auth ein einfaches Observable? – cortopy

5

canActivate dass löst auch eine boolean

1

Sie könnten Observable verwenden, um den asynchronen Logikteil zu verarbeiten. Hier ist der Code, den ich zum Beispiel test:

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); 
     }); 
    } 
    } 
} 
Verwandte Themen