2016-05-11 17 views
5

Ich versuche, ein RxJS BehaviorSubject zu verwenden, das eine boolean enthält, die angibt, ob ein Benutzer in der Anwendung verbunden/angemeldet ist.Problem mit RxJs BehaviorSubject-Abonnent wird nicht über Wertänderung benachrichtigt

Hier ist die Komponente, dh true auf den neuen BehaviorSubject Wert abonniert hat, wenn der Benutzer authentifiziert hat:

import {Component, OnInit} from '@angular/core'; 
import {CollapseDirective} from 'ng2-bootstrap'; 
import {PublicNavbarComponent} from './public.navbar.component'; 
import {PrivateNavbarComponent} from './private.navbar.component'; 
import {SessionService} from '../../session/session.service'; 

@Component({ 
    selector: 'navbar', 
    templateUrl: 'app/shared/components/navbar.component.html', 
    providers: [SessionService], 
    directives: [PublicNavbarComponent, PrivateNavbarComponent, CollapseDirective] 
}) 
export class NavbarComponent implements OnInit { 

    constructor(private sessionService:SessionService) { 
    } 

    ngOnInit() { 
     this.sessionService.authenticated$.subscribe({ 
      next: (value)=> this.isAuthenticated = value 
     }); 
    } 

    isAuthenticated:boolean = false; 

    isCollapsed:boolean = true; 
} 

ist die Klasse/Service enthält die BehaviorSubject:

import {Injectable} from '@angular/core'; 
import {Http, Headers, RequestOptions} from '@angular/http'; 
import {Credentials} from '../shared/models/credentials.model'; 
import {BehaviorSubject} from 'rxjs/BehaviorSubject'; 
import 'rxjs/Rx'; 

@Injectable() 
export class SessionService { 

    authenticated$:BehaviorSubject<boolean> = new BehaviorSubject(false); 
    currentUserAccount; 

    constructor(private http:Http) { 
    } 

    signin(credentials:Credentials) { 
     let headers = new Headers({'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'}); 
     let options = new RequestOptions({headers: headers}); 
     this.http.post('/api/signin', 'username=' + credentials.username + '&password=' + credentials.password, options) 
      .subscribe(response=> 
       this.setPersonalInfo(response.headers.get('x-auth-token')) 
      ); 
    } 

    setPersonalInfo(sessionToken) { 
     localStorage.setItem('authenticated', 'true'); 
     localStorage.setItem('sessionToken', sessionToken); 
     this.authenticated$.next(true);//next() from false to true 
     this.http.get('/api/utils/current-useraccount') 
      .subscribe(param => this.currentUserAccount = param); 
    } 
} 

jedoch Dies hat nicht das erwartete Verhalten: Es scheint, dass authenticated$ vom Sitzungsdienst nur innerhalbwahr istFunktion und isAuthenticated von wird überhaupt nicht benachrichtigt, wenn this.authenticated$.next(true) aufgerufen wird.

Antwort

7

Es scheint, als ob Sie mehrere Instanzen von SessionService haben. z.B. Sie haben es mehrmals angegeben und die Instanz, die Sie signin aufrufen, ist nicht dieselbe Instanz wie die, die Sie in NavbarComponent injiziert haben.

Es hängt von Ihrem Projektentwurf ab, wie Sie Ihre Dienstleistungen erbringen. Normalerweise sind Session-Dienste Singletons.
Ich empfehle, providers: [SessionService], von zu entfernen.

+0

Vielen Dank! Das war in der Tat das Problem ... – balteo

+0

Vielen Dank @Abdulrahman –

1

biete ich in der Regel SessionService bei Bootstrap (und nicht mit providers: []) Sie während des gesamten App eine globaleSessionService Instanz stellen Sie sicher zu teilen.

bootstrap(AppComponent, 
      [SessionService]); 
+0

Ich mag 'bootstrap()' auch, weil es es offensichtlicher macht, dass die Anbieter global sein sollen, aber nach dem Styleguide sollten globale Anbieter nicht sein hinzugefügt zu 'bootstrap()', sondern stattdessen zu der Root-Komponente. Dafür gibt es keine technischen Gründe. Sie halten es nur für aufrechterhaltbar. –

Verwandte Themen