为什么Angular中BehaviorSubject结合switchMap与async pipe出现返回异常?
前提说明
你当前的核心基础场景:没有启用shareReplay(1)时,模板中4个async pipe会对loginStatus$产生4个完全独立的订阅,每个订阅的pipe逻辑都会独立执行,互不共享。
问题1:为什么更新BehaviorSubject的值会导致其他3次请求的响应丢失?
核心原因是switchMap操作符的特性:只要上游发射了新值,switchMap会立即取消当前正在执行的内部Observable订阅,转而订阅新值对应的内部Observable。
你在第一个HTTP请求的map回调中执行了this.loginStatus.next(true),此时BehaviorSubject作为所有订阅的上游,会立刻给4个订阅都推送新值true:
- 另外3个还未返回的HTTP请求对应的内部Observable会被
switchMap直接取消订阅,就算后续HTTP响应返回也不会触发任何回调,看起来就像响应丢失了。
问题2:为什么4次订阅都拿到了true值,第一次订阅也没拿到预期的'fool'?
你执行this.loginStatus.next(true)的时机早于map返回'fool'的时机,执行顺序是:
- 第一个HTTP请求响应返回,进入
map回调 - 先执行
this.loginStatus.next(true),触发所有订阅的上游推送新值true - 所有4个订阅的
switchMap收到新值true,立即取消各自当前的内部流订阅,转而返回of(true) - 此时第一个订阅的
map才返回'fool',但对应的内部流已经被switchMap取消,'fool'不会向下游传递到tap
最终所有订阅的下游收到的都是of(true)发射的true值。
问题3:这是否意味着BehaviorSubject值变化时会取消后续处理流程?
不是BehaviorSubject本身的特性导致的流程中断,完全是switchMap的行为规则导致的:switchMap只认上游的新值,不管上游是什么类型的Observable,只要上游发新值,就会中断当前内部流的处理。你这里恰好上游是BehaviorSubject,所以它的值变化才会触发switchMap的取消逻辑。如果想避免这个问题,要么保留shareReplay(1)让多个订阅共享同一条流,要么把loginStatus.next(true)的执行时机放到当前流处理完成之后。
内容的提问来源于stack exchange,提问作者Suspended
相关产品推荐
相关产品推荐

