【问题标题】:Shared observable and startWith operator共享 observable 和 startWith 运算符
【发布时间】:2017-06-20 16:15:07
【问题描述】:

我有一个关于多播 observables 和我注意到的(对我而言)意外行为的问题。

const a = Observable.fromEvent(someDom, 'click')
  .map(e => 1)
  .startWith(-1)
  .share();

const b = a.pairwise();

a.subscribe(a => {
  console.log(`Sub 1: ${a}`);
});

a.subscribe(a => {
  console.log(`Sub 2: ${a}`)
});

b.subscribe(([prevA, curA]) => {
  console.log(`Pairwise Sub: (${prevA}, ${curA})`);
});

所以,有一个共享的 observable a,它在每次点击事件时发出 1。由于 startWith 运算符而发出 -1。 observable b 只是通过将 a 中的最新两个值配对来创建一个新的 observable。

我的期望是:

[-1, 1] // first click
[ 1, 1] // all other clicks

我观察到的是:

[1, 1] // from second click on, and all other clicks

我注意到的是,值 -1 立即发出并被 Sub 1 消耗,甚至在 Sub 2 订阅 observable 之前,并且由于 a 被多播,Sub 2 对聚会来说太晚了。

现在,我知道我可以通过 BehaviourSubject 进行多播而不使用 startWith 运算符,但我想了解当我使用 startWith 和通过共享进行多播时这种场景的用例。

据我所知,每当我使用 .share() 和 .startWith(x) 时,只有一个订阅者会收到 startWith 值的通知,因为所有其他订阅者都是在发出该值后订阅的。

这是通过某些特殊主题(行为/重播...)进行多播的原因,还是我错过了有关此 startWith/share 场景的某些内容?

谢谢!

【问题讨论】:

  • 我面临同样的问题。您能否提供一个有关 BehaviourSubject 的示例?

标签: rxjs rxjs5


【解决方案1】:

这实际上是正确的行为。

.startWith() 将其价值发送给每个新订阅者,而不仅仅是第一个订阅者。 b.subscribe(([prevA, curA]) 从未收到它的原因是因为您正在使用多播与.share()(又名.publish().refCount())。

这意味着第一个a.subscribe(...) 使.refCount() 订阅它的源并且它将保持订阅状态(请注意,Observable .fromEvent(someDom, 'click') 永远不会完成)。

然后,当您最终调用b.subscribe(...) 时,它只会订阅.share() 中的Subject,并且永远不会通过.startWith(-1),因为它是多播的并且已经在.share() 中订阅。

【讨论】:

  • 嘿!这也是我所理解的,非常感谢您详细说明为什么观察是有意义的。这种情况的一种解决方案也是使用可连接的 observables 并在设置订阅后调用 connect。这样所有订阅者都将获得 startWith 值。
猜你喜欢
  • 1970-01-01
  • 2017-12-31
  • 1970-01-01
  • 2017-05-14
  • 1970-01-01
  • 2017-01-04
  • 2021-05-25
  • 2019-06-13
  • 1970-01-01
相关资源
最近更新 更多