2017-07-13 4 views
1

auf Antwort vom Server hängt habe ich einen Singleton Service:Angular 2. Garde, die

export class CarService { 
    public currentCar: BehaviorSubject<Car> = new BehaviorSubject(null); 
    constructor(private jsonApiService: JsonApiService) { 

     this.jsonApiService.get(`.../activeCar`); 
     .subscribe(data => { 
      if(data) { 
       this.setActiveCar(data); 
      } 
     }) 
    } 
    } 

    public setActiveCar(activeCar: Car): void { 
    this.currentBrokerageAccount.next(activeCar); 
    } 
} 

Dann habe ich currentCar in der Wache verwenden:

canActivateChild(childRoute: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean { 
    if (!this.canActivate()) { 
     return false; 
    } 
    if (!this.carService.currentCar.getValue() && state.url !== '/settings') { 
     this.router.navigate(['/settings']); 
    } 

    return true; 
} 

die Wache überprüft aktuelles Auto und wenn es Ist es Daten erlaubt dann die Seite zu öffnen, ansonsten wird auf die Einstellungsseite weitergeleitet wo der Benutzer das Auto auswählen muss. Also, das Problem ist, wenn ich Menü in der Anwendung dann alles funktioniert, aber wenn ich Seite beim ersten Mal (oder F5) öffne, dann werde ich immer auf die Einstellungsseite umgeleitet. Ich verstehe den Grund: Es ist, weil carService hat das aktive Auto von einem Server noch nicht und currentCar ist null. Wie man es richtig löst?

PS. Der Ablauf ist wie folgt: Nach der Authentifizierung sieht der Benutzer alle Funktionen in der Anwendung, wenn Auto ausgewählt ist. Aber wenn Auto nicht ausgewählt ist, ist nur eine URL verfügbar und es ist die settings. Also, wenn Auto nicht ausgewählt ist, leite ich den Benutzer auf die Einstellungsseite um.

Antwort

1

Das BehaviourSubject, das Sie anfordern, bewertet das ausgewählte Auto wahrscheinlich noch vom Server. Sie können ein AsyncSubject verwenden, das den Wert abruft und dann abschließt, und anstatt den aktuellen Wert aus dem Dienst "anzufordern", sollten Sie den Betreff abonnieren und ihn den Wert weitergeben lassen.

//in your service 
currentCar$ : AsyncSubject<Car> = new AsyncSubject(); 
this.jsonApiService.get(`.../activeCar`).subscribe(
    (car) => { 
     currentCar$.next(car); 
     currentCar$.complete(car); 
    } 
); 

//in your guard 
//instead of getValue() subscribe to the AsyncSubject 
//you should probably handle the "null" case too 
this.carService.currentCar$.subscribe(
    (car) => { 
     if (!car && state.url !== '/settings'){ 
      this.router.navigate(['/settings']); 
     } 
    } 
); 

Die Subskription empfängt den Wert, der kurz vor dem Abschluss von AsyncSubject ausgegeben wird.

+0

Die AsyncSubject ist das, was ich brauche. Vielen Dank, – user348173

0

versuchen, diesen Ansatz

export class CarService { 

    private data: any; 

    constructor(private jsonApiService: JsonApiService) { 
    } 
    getCar(): Observable<any> { 
     return this.jsonApiService.get('url') 
     .map((response: Response) => { 
      this.data = response.json().data; 
      return this.data; 
      } 
     ); 
    } 

    hasCarData() { 
     return data ? true : false; 
    } 
    } 

    public setActiveCar(activeCar: Car): void { 
    this.currentBrokerageAccount.next(activeCar); 
    } 
} 

canActivateChild(childRoute: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean { 
    if (!this.canActivate()) { 
     return false; 
    } 

    if(state.url !== '/settings') { 
     this.carService.getCar() 
     .subscribe((data: any) => { 
     if (!this.carService.hasCarData()) { 
      this.router.navigate(['/settings']); 
     } else { 
      return true; 
     } 
     }); 
    } else { 
     return true; 
    } 
}