RxJS状态变更为何乱序?订阅者交互导致执行顺序问题咨询
嘿,我来帮你拆解这个问题的根源,以及怎么修复它~
你遇到的乱序/多余输出问题,本质是同步嵌套调用subject.next()导致的订阅者执行顺序和distinctUntilChanged的基准值被意外修改。我们一步步理清楚代码的执行流程:
初始化阶段:
- 你创建了
BehaviorSubject并初始next({value: 'Test1'}),此时它的当前值是这个对象。 - 订阅
h2时,BehaviorSubject会立即把当前值推给v2,pluck('value2')得到undefined,所以第一次输出v2 undefined。
- 你创建了
关键执行步骤:
- 当你调用
subject.next({value: 'Test2'})时,RxJS会同步遍历所有订阅者:- 先处理
h1的订阅:v1的pluck('value')得到'Test2',和之前的'Test1'不同,触发回调。 - 回调里同步调用
subject.next({value: 'Test2', value2: true}),这会立即触发新一轮的订阅者遍历:- 处理
v2时,pluck('value2')得到true,和上一次的undefined不同,输出v2 true,同时distinctUntilChanged的基准值更新为true。
- 处理
- 回到第一轮的遍历,继续处理
h2的订阅:此时处理的是最初的{value: 'Test2'},pluck('value2')得到undefined,和当前distinctUntilChanged的基准值true不同,所以又输出了v2 undefined——这就是你看到的多余输出。
- 先处理
- 当你调用
修复方案
核心是避免在订阅回调里同步触发新的next,让第一轮的所有订阅者处理完成后,再执行新的next。有两种常用方式:
方式1:用setTimeout把新的next放到异步队列
修改h1的订阅回调:
h1 = v1.subscribe(function(it) { if (it == 'Test2') { setTimeout(() => { subject.next({value: it, value2: true}) }, 0); } })
方式2:用RxJS的asyncScheduler(更符合RxJS风格)
先导入asyncScheduler(RxJS 6+版本),然后用它调度next:
import { asyncScheduler } from 'rxjs'; h1 = v1.subscribe(function(it) { if (it == 'Test2') { asyncScheduler.schedule(() => { subject.next({value: it, value2: true}) }); } })
这样修改后,第一轮的next({value: 'Test2'})的所有订阅者会先处理完成,v2的distinctUntilChanged基准值更新为undefined,之后再执行新的next,就能得到你预期的输出:
v2 undefined v2 true
内容的提问来源于stack exchange,提问作者RMorrisey
相关产品推荐
相关产品推荐

