RxJs BehaviorSubject 的订阅者未收到值更改通知的问题
Issue with RxJs BehaviorSubject's subscriber not being notified of value change
我正在尝试使用包含 boolean
的 RxJS BehaviorSubject
,表示应用程序中用户是否 connected/logged。
这是订阅新 BehaviorSubject
值的组件,即 true
当用户已通过身份验证时:
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;
}
这是包含 BehaviorSubject
的 class/service:
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);
}
}
然而,这并没有预期的行为:似乎来自会话服务的 authenticated$
仅在 setPersonalInfo
函数中为真,而来自 NavbarComponent
的 isAuthenticated
似乎不是调用 this.authenticated$.next(true)
时完全通知。
您似乎有多个 SessionService
。例如您提供了不止一次,并且您在其中调用 signin
的实例与您在 NavbarComponent
.
中注入的实例不同
这取决于你的项目设计,你如何提供你的服务。通常session服务都是单例的。
我建议从 NavbarComponent
.
中删除 providers: [SessionService],
我通常在 bootstrap(而不是 providers: []
)提供 SessionService
,以确保您共享 一个全球 SessionService
贯穿整个应用程序的实例。
bootstrap(AppComponent,
[SessionService]);
我正在尝试使用包含 boolean
的 RxJS BehaviorSubject
,表示应用程序中用户是否 connected/logged。
这是订阅新 BehaviorSubject
值的组件,即 true
当用户已通过身份验证时:
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;
}
这是包含 BehaviorSubject
的 class/service:
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);
}
}
然而,这并没有预期的行为:似乎来自会话服务的 authenticated$
仅在 setPersonalInfo
函数中为真,而来自 NavbarComponent
的 isAuthenticated
似乎不是调用 this.authenticated$.next(true)
时完全通知。
您似乎有多个 SessionService
。例如您提供了不止一次,并且您在其中调用 signin
的实例与您在 NavbarComponent
.
这取决于你的项目设计,你如何提供你的服务。通常session服务都是单例的。
我建议从 NavbarComponent
.
providers: [SessionService],
我通常在 bootstrap(而不是 providers: []
)提供 SessionService
,以确保您共享 一个全球 SessionService
贯穿整个应用程序的实例。
bootstrap(AppComponent,
[SessionService]);