You need to enable JavaScript to run this app. RxJS race操作符为何在两源流均未完成时停止输出后续值
优惠活动
大模型
产品
解决方案
定价
更多

RxJS race操作符为何在两源流均未完成时停止输出后续值

为什么b$的后续值完全不输出

核心原因是你对race操作符的运行机制存在误解,它的工作逻辑根本不是“并行接收所有源的发射,直到第一个源停止发射后再接管其他源”。
实际运行流程拆解如下:

  1. 当race([a$, b$])被订阅时,会同步订阅所有传入的源,给每个源绑定临时监听逻辑,等待第一个源发出任意类型的通知(包括next值、error、complete)。
  2. 一旦某个源发出了第一个通知,会立刻触发胜者判定流程,同时执行两个不可逆的动作:
    • 直接退订剩下所有还没发出过第一个通知的源
    • 将后续的透传通道完全绑定到这个发出第一个通知的源上:该源后续发射的所有next值、error、complete事件,都会直接透传给race的下游订阅者,和其他没选中的源再也没有关系。

对应到你的代码场景:

  • race刚订阅a$和b$时,b$作为interval(1000),第一个值需要等待1秒才会发射;
  • 紧接着你通过[1,2,3,4,5,6,7].map(i => a$.next(i))同步触发a$连续发射值,a$发出的第一个值1会直接成为触发胜者判定的信号,a$瞬间被选为胜者;
  • 判定完成的瞬间,race会立刻退订b$,b$绑定的1秒定时逻辑会被直接清除,后续到点后根本不会触发值发射。你看到的控制台输出的1-7全部是a$作为被选中的源透传出来的值,整个过程里b$甚至连第一个值都还没来得及发,就已经被退订了,自然也就不会有后续的1输出。
race操作符是否感知到a$不会再发新值?

完全没有。race从始至终都不会去判断被选中的源后续会不会继续发射值、会不会停止发射。它甚至从a$被选中的那一刻起,就已经把b$彻底从监听列表里删除了,根本没有感知b$后续状态的基础。

你预期的“a$发完7个值后轮到b$发射”的逻辑,和race的设计完全不沾边:race的竞速逻辑是“比谁第一个发出通知,第一个冒头的源独占所有透传通道,其他源直接被丢弃”,根本不存在“等胜者发完再换其他源”的机制。

race的源选择感知逻辑

race的感知逻辑非常直白,没有复杂的状态判断,只盯一件事:哪个源是第一个发出通知的

  • 它不会主动追踪“源是不是已经发完所有值”
  • 不会在选中源结束后自动切换到其他源
  • 被退订的源不会再有任何被重新订阅的可能

你可以做个对称验证:如果调整代码,让a$延迟1.5秒再发射第一个值,b$会因为1秒先发射成为胜者,此时race会立刻退订a$,不管a$后续再发多少值,都不会有任何输出——这和你当前代码里a$先冒头、b$被退订的逻辑是完全一致的。


内容的提问来源于stack exchange,提问作者Roy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.26 17:54:04