angular - BehaviorSubject 不发射值
问题描述
在我的 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
似乎没有被发送/接收。
解决方案
ngOnDestroy
在从 observable 获取最新值之前调用不一定正确。
这取决于执行操作所需的逻辑或时间。在您的情况下,logout
需要更多时间,并且在它完成之前ngOnDestroy
被调用并且您的订阅被销毁。
例如,考虑stackblitz上的代码。如果您在test.service.ts文件中看到,我创建了 2 个函数,如下所示:
...
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
正在订阅和安慰价值并在销毁时取消订阅,如下所示:
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
添加一些延迟。
推荐阅读
- javascript - Emscripten 在 C++ 中的等待运算符。返回未定义而不是字符串值
- javascript - 在 iFrame 中使用 Window.find() 时如何禁用自动滚动
- mongodb - Mongo Java Driver 版本与 Spring 框架不匹配
- html - 向构造函数添加模态对话框可以消除页面上的所有其他内容
- github-api - Github restapi:如何过滤用户的拉取请求?
- swift - AVMetaDataObject.bounds 到 SwiftUI 位置?
- c# - 使用 .txt 的 C# 应对数组
- c++ - 是否可以使用多个仿函数创建优先级队列?
- tkinter - 一起拖放多个小部件?
- reactjs - 试图在函数中获取标签键但显示为“”