【问题标题】:Second subscription to a shared mapping from BehaviorSubject does not execute从 BehaviorSubject 对共享映射的第二次订阅不执行
【发布时间】:2017-12-04 09:45:57
【问题描述】:

当我从 BehaviorSubject 实例 (t) 订阅共享映射时,只执行第一个订阅。

当原始BehaviorSubject (obj) 发出第二个值时,仅打印最新值,并且两个订阅都已执行。

让我们检查一下我的代码

const obj = new Rx.BehaviorSubject(1)
obj.subscribe(console.log)
const t = obj.map(u => {
  console.log("mapped")
  return u * 10
}).share()

t.subscribe(x => console.log("subscribe 1 " + x))
t.subscribe(x => console.log("subscribe 2 " + x))
//with the following line un-commented, both subscriptions print out new value
//obj.next(2)

我的预期结果是

1
mapped
subscribe 1 10
subscribe 2 10

但实际结果是

1
mapped
subscribe 1 10

抱歉这个幼稚的问题。有谁能给我解释一下吗?

非常感谢

【问题讨论】:

    标签: rxjs behaviorsubject


    【解决方案1】:

    任何操作员(包括share)实际上都会创建一个新的 Sub-Observable,它具有自己的共享/重播属性,这些属性与源 Observable 分离。

    所以要获得结果,您应该使用publishReplay(1) 而不是share()。 (对于publishReplay,您当然必须使用refCount()connect()

    const obj = new Rx.BehaviorSubject(1)
    obj.subscribe(console.log)
    const t = obj.map(u => {
      console.log("mapped")
      return u * 10
    }).publishReplay(1)
    .refCount();
    
    t.subscribe(x => console.log("subscribe 1 " + x))
    t.subscribe(x => console.log("subscribe 2 " + x))
    //with the following line un-commented, both subscriptions print out new value
    //obj.next(2)
    <script src="https://unpkg.com/rxjs/bundles/Rx.min.js"></script>

    【讨论】:

      【解决方案2】:

      在您的示例中,您有两个主题:

      • obj 中的BehaviorSubject

      • Subject 内部的实例.share()

      请记住,BehaviorSubject只有在您订阅它时才会发出其缓存值

      第一个观察者obj.subscribe(console.log) 直接订阅BehaviorSubject。这将打印1

      然后您创建一个以share() 运算符结尾的链t

      现在您使用t.subscribe 订阅t。这意味着您订阅了share() 内的Subject,因为这是它的第一个观察者,它需要订阅它的源Observable(反过来又到达发出其缓存值的源BehaviorSubject)。请注意,share() 只是将multicast() 运算符与refCount() 结合使用的快捷方式。

      最后一行您再次订阅t.subscribe。就像以前一样,这订阅了share() 内的Subject。然而share() 已经订阅了它的源 Observable,所以它不会再订阅。这就是多播和multicast() 运算符的意义所在。

      这就是为什么您看不到任何subscribe 2 10 并且您不会看到mapped 打印两次的原因。您订阅的是share() 中的Subject,而不是源BehaviorSubject

      【讨论】:

      • 您知道如何将BehaviorSubject 映射到另一个BehaviorSubject。我不想在每个订阅上重复map 中的逻辑,只需要在原始BehaviorSubject 实例(obj)发出新值时运行此逻辑。换句话说,我希望在我的问题中将结果打印为 expected result
      • 我认为我从@olsn 的回答中得到了答案。谢谢
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-09-06
      • 2022-01-21
      • 2020-03-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多