2016-05-11 8 views
5

Próbuję użyć RxJS BehaviorSubject, który zawiera boolean określający, czy użytkownik jest podłączony/zalogowany w aplikacji.Problem z subskrybentem RxJs BehaviorSubject nie jest powiadamiany o zmianie wartości

Oto składnik, który aspiruje do nowego BehaviorSubject wartości tj true gdy użytkownik uwierzytelniony:

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

Oto klasa/serwis zawierający 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); 
    } 
} 

jednak nie ma oczekiwanego zachowania: wygląda na to, że authenticated$ z usługi sesji jest prawdziwe tylko w ciąguFunkcjai isAuthenticated od NavbarComponent nie jest powiadamiana w ogóle, gdy zostanie wywołana this.authenticated$.next(true).

Odpowiedz

7

Wygląda na to, że masz wiele instancji SessionService. na przykład podałeś go więcej niż jeden raz, a instancja, którą wywołujesz, nie jest tą samą instancją, którą wywołałeś w NavbarComponent.

Zależy od projektu projektu, w jaki sposób świadczysz swoje usługi. Zwykle usługi sesji są pojedyncze.
Polecam usunięcie providers: [SessionService], z .

+0

Wielkie dzięki! To był rzeczywiście problem ... – balteo

+0

Wielkie dzięki @Abdulrahman –

1

zwykle zapewniają SessionService w bootstrap (a nie z providers: []), aby upewnić się dzielić jeden globalnySessionService wystąpienie w całej aplikacji.

bootstrap(AppComponent, 
      [SessionService]); 
+0

Ja też lubię 'bootstrap()', ponieważ sprawia to bardziej oczywiste, że dostawcy mają być globalni, ale zgodnie z przewodnikiem po stylu, globalni dostawcy nie powinni być dodane do 'bootstrap()', ale zamiast tego do komponentu root. Nie ma ku temu technicznych przyczyn. Po prostu uważają, że jest to łatwiejsze do utrzymania. –

Powiązane problemy