2016-03-24 7 views
1

Inspiriert durch das Beispiel bei angular.io (Eltern und Kinder kommunizieren über einen Dienst) Ich implementierte ein Observer/beobachtbares Muster, um meine Navigationskomponente zu benachrichtigen, ob der Benutzer authentifiziert ist. Das Problem ist, dass die Navigationskomponente nur eine Benachrichtigung erhält, wenn der Benutzer sich abmeldet.Beobachter erhält nur Wert von einem nächsten Anruf

Mein Authentifizierungsdienst wie folgt aussieht:

export class AuthenticationService { 

    private isAuthenticatedSource = new Subject<boolean>(); 

    isAuthenticated$ = this.isAuthenticatedSource.asObservable(); 

    constructor(private http : AuthHttp) {} 

    login(email: string, password: string) { 
    ... 
    this.isAuthenticatedSource.next(true); 
    ... 
    } 

    logout() { 
    ... 
    this.isAuthenticatedSource.next(false); 
    ... 
    } 

} 

ich dafür gesorgt habe, dass beiden Anrufe (Login- und Logout) gemacht werden und keine Fehler geworfen werden. Meine Navigationskomponente wie folgt aussieht:

export class NavigationComponent implements OnDestroy, OnInit { 

    private subscription: Subscription; 

    isAuthenticated: boolean; 

    constructor(private authService: AuthenticationService, 
       private router: Router) { 
    this.isAuthenticated = authService.isAuthenticated(); 
    } 

    logout(event) { 
    event.preventDefault(); 
    this.authService.logout(); 
    this.router.navigate(["Authentication", "Login"]); 
    } 

    ngOnDestroy() { 
    this.subscription.unsubscribe(); 
    } 

    ngOnInit() { 
    this.subscription = this.authService.isAuthenticated$.subscribe(
     value => console.log("updated to:", value) 
    ); 
    } 

} 

Die Konsole sollte lügt „Aktualisiert: true“, wenn Sie sich anmelden und „Aktualisiert: false“ beim Abmelden. Das Problem ist, dass beim Abmelden nur eine Nachricht angezeigt wird. Offensichtlich erhält der Beobachter beim Einloggen nicht den Wert (true). Hoffentlich können Sie erklären, warum dies geschieht.

aktualisieren

Der Anruf jetzt unten enthalten ist, um sich einzuloggen. Es wird von meinem LoginComponent aufgerufen, wenn ein Benutzer ein (Login) Formular einreicht. LoginComponent wie folgt aussieht:

export class LoginComponent { 

    public email : string; 
    public password : string; 
    public errors : any; 
    public next : any; 

    constructor(private authService : AuthenticationService, 
       private router : Router, 
       private params : RouteParams) { 
    // default to navigate to dashboard on successfull login 
    let next = this.params.get("next") || "/Dashboard"; 
    this.next = [next]; 
    } 

    login(event) { 
    event.preventDefault(); 
    this.authService.login(this.email, this.password) 
         .subscribe(
         data => this.router.navigate(this.next), 
         errors => this.errors = errors); 
    } 

} 

Die entsprechende Vorlage einen einzigen Anruf hat sich einloggen: <form (submit)="login($event)">. Login wird nicht an anderen Stellen in der Anwendung aufgerufen.

+0

Sie können bereits im Konstruktor subskribieren, ohne auf 'ngOnInit() 'warten zu müssen, wenn der Code nicht davon abhängt, dass Eingaben aktualisiert werden. Vielleicht wurde das Ereignis bereits gesendet, bevor die 'NavigationComponent' abonniert wurde. Ich denke, dass Sie ein 'BehaviorSubject' benötigen, um den letzten Wert sofort nach dem Abonnieren zu erhalten. –

+0

Ich sehe den Aufruf von 'login' in Ihrem Code nicht - Sind Sie sicher, dass Sie das _after_ anrufen, nachdem Sie den Betreff abonniert haben? Ein Subjekt sendet nur Ereignisse nach Subskription an Subskribenten - möglicherweise möchten Sie eine andere Art von Subjekt, vielleicht 'BehaviorSubject' – tddmonkey

+0

Danke für die Rückmeldung. Versuchte BehaviorSubject und es hat nichts geändert. Ich werde auch den Subskriptionsaufruf an den Konstruktor verschieben, aber die Situation ist immer noch dieselbe. @tddmonkey Ja bin ich mir sicher. Login wird aufgerufen, wenn ein Benutzer auf eine Schaltfläche klickt - lange nachdem NavigationComponent den Betreff abonniert hat. – ThaBird

Antwort

0

Ich bin nicht excactly sicher, warum es funktioniert, aber isAuthenticatedSource als statische Variable behebt das Problem zu setzen. Ich muss noch mehr recherchieren, um zu verstehen warum. Vielen Dank für Ihr Feedback.

2

Ich sehe nicht, wo Sie Login angerufen haben. Ich habe jedoch ein Beispiel aufgegriffen, das zeigt, dass das Aufrufen der Anmeldung am Dienst, bevor die UI-Abonnenten Ihre Beobachtung reproduzieren, zeigt, dass die Benutzeroberfläche nicht aktualisiert wird. Der Aufruf authService.login() im Konstruktor von AppComponent hat keine Auswirkungen auf die Benutzeroberfläche. Dies liegt daran, dass das Abonnement später in ngOnInit passiert ist. Ich hoffe, das ist nützlich.

http://plnkr.co/edit/fteTLPCJUucCVKdVzJuP

export class AppComponent implements OnDestroy, OnInit { 

    @Output subscribe: string; 
    private subscription: Subscription; 
    private authService: AuthenticationService; 

    constructor(private authService: AuthenticationService) { 
    this.subscribe = 'not set'; 
    this.authService = authService; 

    authService.login('john', 'password'); // has no affect on UI since login happens before subscribe in ngOnInit 
    } 

    login() { 
    this.authService.login('john', 'password'); 
    } 

    logout() { 
    this.authService.logout(); 
    } 

    ngOnInit() { 
    this.subscription = this.authService.isAuthenticated$.subscribe(
     //value => console.log("updated to:", value) 
     value => this.subscribe = '' + value; 
    ); 
    } 

} 
+0

Schönes Beispiel. Das Problem besteht jedoch weiterhin. Ich habe meine Frage aktualisiert, um auch den Anruf zur Anmeldung einzuschließen. Wie Sie sehen können, geschieht dies nach dem Abonnieren von 'NavigationComponent'. – ThaBird

Verwandte Themen