RxJS observers 是否总会处理observable完成前提交的所有事件?
核心结论
首先明确RxJS的核心契约要求:所有符合规范的操作符必须严格遵循零或多个next通知 -> 最多1个complete/error通知的顺序,因此complete调用前通过next提交的所有事件,一定会被正常下发到下游,不会被无故丢弃。
你给出的两段代码对比
你举的delay场景下,两段代码的运行结果完全一致:
第二段代码中,subj.next('1')和subj.complete()是同步依次调用的,delay操作符会对所有收到的通知(包括next、complete)都做相同时长的延迟,同时保留原有的通知顺序,因此500ms后依然会先触发next回调打印值,再收到complete通知,不存在丢值的问题。
需要在next回调中调用complete的场景
大部分场景下next后立刻调用complete是安全的,但以下场景更适合等observer处理完事件再触发complete:
- 你的业务逻辑依赖这个Subject的
complete事件判断整体流程是否结束,且订阅者的next回调中存在异步处理逻辑:如果next后立刻调用complete,complete通知会在异步逻辑执行完毕前触发,导致流程判断出错。// 反例:complete会早于异步处理逻辑执行完毕 const subj = new Subject() subj.subscribe(async () => { await saveDataToDB() // 异步IO操作 console.log('数据保存成功') }) subj.next('要保存的数据') subj.complete() // 此时saveDataToDB还没执行完 - 多订阅者场景下,需要保证所有订阅者都完成
next对应的业务处理后,再执行complete触发后续的收尾逻辑。
额外注意的影响因素
- 特殊Subject类型:
AsyncSubject只有在调用complete后才会发送最后一个next值,必须要显式调用complete才能正常下发值;ReplaySubject在complete后新加入的订阅者依然可以收到历史缓存值,和complete的调用时机无关。 - 自定义操作符风险:如果你使用了不符合RxJS规范的自定义操作符,可能存在收到
complete通知后直接丢弃未处理next事件的问题,RxJS官方内置的操作符都不存在这个问题。
内容的提问来源于stack exchange,提问作者Rudolf Traunmüller
相关产品推荐
相关产品推荐

