angular - 有人能解释一下为什么 BehaviorSubject 结果会这样吗?
问题描述
我编写了一个服务,其中包含一个名为 loginStatus 的 BehaviorSubject 和一个返回它的函数。
private loginStatus = new BehaviorSubject<boolean>(false);
getLoginStatus(): Observable<boolean> {
return this.loginStatus;
}
然后我在其他组件的 DOM 中使用 4 个不同 div 中的异步管道订阅它,我只是评论了 shareReplay 以显示我想知道的内容。
loginStatus$ = this.authService.getLoginStatus().pipe(
switchMap(res => {
if (!res) { return this.authService.isLoggedIn(); }
else { return of(res); }
}),
tap(res => console.log('tap: ' + res)),
//shareReplay(1),
);
isLoggedIn 是一个 http 请求,用于检查我是否登录,我检查 switchMap 中的 loginStatus 值,如果它是 false 则调用 isLoggedIn
isLoggedIn(): Observable<boolean> {
console.log('called isLoggedIn');
return this.httpService.get('/auth/isLoggined').pipe(
map(res => {
console.log('isLoggedIn res: ' + JSON.stringify(res));
if (res) {
this.loginStatus.next(true);
this.firstName = res.first_name;
this.lastName = res.last_name;
this.tel = res.tel;
return 'fool';
} else {
this.clearAll();
return false;
}
}),
最后这是我的控制台结果:
called isLoggedIn
called isLoggedIn
called isLoggedIn
called isLoggedIn
由于我的 4 个异步管道,isLoggedIn 被调用了 4 次,并且 loginStatus 为 false。
在第一个 http 请求响应时,我得到了一个像 {first_name:xxx, last_name:yyy, 1234} 这样的 json 对象,所以我将 true 推送到 loginStatus 并将“傻瓜”返回给进一步的操作员。
我想我会在 loginStatus$ 的点击运算符中得到傻瓜,但事实并非如此。
isLogedIn res: {"logined":true,"first_name":"xxx","last_name":"yyy","tel":"1234"}
tap: true
tap: true
tap: true
tap: true
我只得到了第一个 isLoggedIn 请求的响应,其他 3 个丢失了。而且我永远不会傻瓜,我猜所有的异步管道都从 loginStatus BehaviorSubject 得到了真实的。
然后我在 isLoggedIn 函数中注释了 this.loginStatus.next(true) 来比较结果。
isLogedIn res: {"logined":true,"first_name":"xxx","last_name":"yyy","tel":"1234"}
tap: fool
isLogedIn res: {"logined":true,"first_name":"xxx","last_name":"yyy","tel":"1234"}
tap: fool
isLogedIn res: {"logined":true,"first_name":"xxx","last_name":"yyy","tel":"1234"}
tap: fool
isLogedIn res: {"logined":true,"first_name":"xxx","last_name":"yyy","tel":"1234"}
tap: fool
这是我更喜欢的结果,我打了 4 次电话,所以我得到了 4 个回复,它把傻瓜传给了水龙头 4 次。
我想知道为什么在第一次订阅过程中更改 BehaviorSubject 时会丢失其他响应。
以及为什么所有 4 订阅都能获得真正的价值,我想至少第一次会得到傻瓜。
这是否意味着 BehaviorSubject 将在更改时取消进一步的过程而不是完成它?
解决方案
发生这种情况是因为您正在使用switchMap
,这将取消以前的内部可观察对象并处理新的。
BehaviorSubject
因此,当您在using中发出值时this.loginStatus.next(true)
,switchMap
运算符将取消先前的 observable 并处理新值(这是真的)。
如果你想实现你的场景,你应该保持之前的内部 observable 正常完成,那么你需要使用mergeMap
orconcatMap
运算符。
推荐阅读
- c++ - 模板中的setValue模板(双模板)
- angular - Angular 2更改路由(URL)并从数据库加载数据
- python - 遍历 pandas 数据框中的 datetime64 列
- powershell - Powershell:不正确的返回为最高值
- sonarqube - 在向 ActiveMQ 发送消息的情况下删除 Thread.sleep()
- android - Android 下载文件到内部应用空间
- c# - 你如何获得远程计算机的主机名?
- r - 使用系统和回声未提供正确的文本
- java - 在 NestedScrollView 中隐藏滚动视图并取而代之
- php - 更新今天 created_at 的记录 - Laravel