第二次订阅来自 BehaviorSubject 的共享映射不执行

Second subscription to a shared mapping from BehaviorSubject does not execute

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

当原始BehaviorSubjectobj)发出第二个值时,仅打印最新值,并执行两个订阅。

让我们检查我的代码

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

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

非常感谢

任何运算符(包括 share)实际上都会创建一个新的 Sub-Observable,它有自己的 share/replay-properties 与 source-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>

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

  • 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.