【问题标题】:In RxJS, why does a pipe get executed once for each subscription?在 RxJS 中,为什么每次订阅都会执行一次管道?
【发布时间】:2019-03-23 07:18:25
【问题描述】:

我希望有多个订阅来对可观察的事件做出反应,但我也想记录该事件,因此我通过一个 do() 操作符将其通过管道进行记录。

问题是,我创建的每个订阅都会记录一次事件!

目前我正在通过创建一个Subject 并从事件回调中调用next 来解决这个问题,这允许我记录一次事件并触发多个订阅。

以下是一些演示该问题的代码:https://stackblitz.com/edit/rxjs-xerurd

我觉得我错过了一些东西,难道没有更“RxJS”的方式来做到这一点吗?

编辑:

我并不是要区分 hot 和 cold observable,实际上我使用的是 hot observable - 由fromEvent() 创建的那个,我想知道为什么我的可能很热的事件源表现得像冷的一样。

我现在意识到 - 在阅读了 share() 之后 - pipe() “转变”了你的可观察到的冷,即根据你的来源返回一个冷的(可能是冷的,可能是热的)

【问题讨论】:

  • 这是 RxJS 应该做的。如果您只想保留一个订阅源,可以使用share() 运算符。
  • 感谢您这么快回答! share() 确实似乎是我正在寻找的东西,但您能否(如果您知道为什么会这样)解释这种设计背后的原因?在我看来,也许“共享”应该是默认设置,“不共享”应该有一个运算符。

标签: javascript rxjs reactive-programming


【解决方案1】:

因为默认情况下可观察序列是冷的,所以每个订阅都会有一组单独的站点效果。

如果您希望副作用只执行一次 - 您可以通过将单个订阅广播给多个订阅者来共享订阅。为此,您可以使用share、shareReplay 等。

为了更好地理解它的工作原理,什么是“冷”和发布,请参阅 RxJS v4 文档:

4.8 Use the publish operator to share side-effects

【讨论】:

  • 如果share() 和多播的东西没有解决你的问题。看我的回答。 ;)
【解决方案2】:

编辑:share() 终于开始工作了。请看下面的cmets。感谢@Oles Savluk。

我把我的答案记录在下面。它可能会有所帮助。


share() 和多播的东西并没有解决我非常相似的问题。

我是这样解决的:https://stackblitz.com/edit/rxjs-dhzisp

const finalSource = new Subject();
fromEvent(button3, "click").pipe(
  tap(() => {
    console.log("this happens only once")
  }) 
).subscribe(() => finalSource.next())

finalSource.subscribe(
  () => console.log("first final subscription")
)

finalSource.subscribe(
  () => console.log("second final subscription")
)

finalSource.subscribe(
  () => console.log("third final subscription")
)

【讨论】:

  • 您基本上是“手动”进行多播的。如果您将share() 紧跟在tap() 之后放在badSource 中,也会发生同样的情况 - 副作用将执行一次。
  • 这完全没问题,但时间更长,而且您不会传播可能导致问题的错误
  • Ooooooooooooooooooooooooooo ......我想我只是想出了一些东西:在我的测试中,我把share() BEFORE 放在tap() 上,确实它没有工作!现在,这对我来说很有意义:它只能“分享”“先于自身”的东西。我需要“共享”AFTER 所有管道。无论如何,非常感谢你的这个小解释(你对错误的不传播是完全正确的......我错过了这部分)......现在感觉很愚蠢! :(
猜你喜欢
  • 2023-03-20
  • 1970-01-01
  • 2019-10-17
  • 1970-01-01
  • 1970-01-01
  • 2016-09-25
  • 1970-01-01
  • 1970-01-01
  • 2019-06-18
相关资源
最近更新 更多