RxJS中BehaviorSubject调用next()是否会阻塞后续代码执行?
BehaviorSubject的next()执行时序结论
默认场景下,调用BehaviorSubject实例的next()方法推送值时,会等待所有已注册订阅者的同步处理逻辑全部执行完成,才会继续运行当前方法内next()之后的后续代码,不会在调用next()后立刻跳到下一行执行。
核心原理
BehaviorSubject继承自基础Subject类,RxJS中这类原生Subject的通知派发默认是完全同步的:调用next()时,程序会同步遍历Subject内部维护的所有有效订阅者列表,按照订阅先后顺序逐个执行每个订阅者对应的next回调,整个遍历执行过程会阻塞当前同步调用栈,直到所有同步回调执行完毕,next()方法才会执行完成出栈,后续代码才会获得执行权。
特殊例外说明
如果订阅者的回调逻辑中包含异步代码(比如主动使用observeOn指定了异步调度器、回调内部写了setTimeout、Promise、async/await这类异步逻辑),这部分异步逻辑不会阻塞next()后续代码的执行——这是JavaScript本身异步任务不阻塞同步栈的特性导致的,和Subject本身的派发逻辑无关,Subject本身的通知触发动作依然是同步的。
验证示例
你可以直接运行下面的代码观察执行顺序,就能直观验证时序:
import { BehaviorSubject } from 'rxjs'; const samples = new BehaviorSubject<unknown>(undefined); // 注册订阅者 samples.subscribe((val) => { console.log('1. 订阅者收到推送值:', val); // 模拟耗时同步逻辑 let count = 0; for (let i = 0; i < 10000000; i++) { count += i; } console.log('2. 订阅者同步处理逻辑执行完毕'); }); console.log('3. 准备调用next()方法'); samples.next(null); console.log('4. next()方法调用后的后续代码执行');
代码运行后的固定输出顺序为:
3. 准备调用next()方法 1. 订阅者收到推送值: null 2. 订阅者同步处理逻辑执行完毕 4. next()方法调用后的后续代码执行
如果next()是异步派发,第4行日志会在1、2行之前打印,实际运行结果可以证明同步执行的结论。
内容的提问来源于stack exchange,提问作者Josh
相关产品推荐
相关产品推荐

