在Angular 7应用程序中,我有一个登录服务和一个管理员,该服务跟踪该人是否已登录。由于某种原因,只能看到来自true
方法的初始login
值。在服务中,我有这个:
private admin = new BehaviorSubject(false);
admin$ = this.admin.asObservable();
login(user: string, pwd: string): Observable<ILoginData> {
sessionStorage.removeItem('admin');
const coded = btoa(`${user}:${pwd}`);
const headers = new HttpHeaders({
'Authorization': `Basic ${coded}`,
});
return this.http
.post<ILoginData>(`${this.baseUrl}/login`, null, {headers: headers})
.pipe(
tap(x => {
sessionStorage.setItem('admin', JSON.stringify(x.admin));
this.admin.next(x.admin);
})
)
}
logout(): void {
sessionStorage.removeItem('admin');
this.admin.next(false);
}
然后app.component.ts
订阅:
private subscription: Subscription;
ngOnInit(): void {
this.subscription = this.producerService.admin$.subscribe(x => {
console.info(`Admin being set to ${x}`);
this.showAdminSection = x;
});
}
ngOnDestroy(): void {
if (this.subscription) {
this.subscription.unsubscribe();
}
}
我看到的是登录订阅时会调用一个值,但是当我调用logout()
方法时,即使我正在发送false
更新,消息仍然是从不打印到控制台,说它已设置为false
。就像只发出第一个值,然后由于某种原因而关闭订阅。
我不确定为什么false
似乎没有被发送/接收。
答案 0 :(得分:0)
在从可观察值获取最新值之前调用ngOnDestroy
不一定是正确的。
这取决于执行操作所需的逻辑或时间。对于您而言,logout
需要更多时间,并且在完成之前,将调用ngOnDestroy
并且您的订阅被销毁。
例如,请考虑此处stackblitz上的代码。如果您在 test.service.ts 文件中看到,我创建了两个函数,如下所示:
...
nextValueDelayed(value: boolean) {
setTimeout(() => {
this._test.next(value);
});
}
nextValue(value: boolean) {
this._test.next(value);
}
...
现在,从 app.component.ts 中,我称呼如下:
...
reverse() {
this.visible = !this.visible;
this._testService.nextValue(this.visible);
}
reverseDelayed() {
this.visible = !this.visible;
this._testService.nextValueDelayed(this.visible);
}
...
这两个函数都通过按钮调用,visible
负责创建和销毁HelloComponent
。
app.component.html
<hello name="{{ name }}" *ngIf="visible"></hello>
<button (click)="reverse()">Reverse</button>
<button (click)="reverseDelayed()">Reverse Delayed</button>
现在,HelloComponent
正在订阅和确认值,并取消订阅destroy,如下所示:
hello.component.ts
...
ngOnInit(){
this.sub = this._testService.test$.subscribe(value=>{
console.log(value);
})
}
ngOnDestroy(){
this.sub.unsubscribe();
}
...
现在,尝试单击Reverse
和Reverse Delayed
按钮,您会看到,当您单击Reverse
时,它将打印所有值。但是,当您单击Reverse Delayed
时,组件将在获得最新值之前被销毁,因为我们已经使用setTimeout
来增加一些延迟。