RxJs:防止无限循环

时间:2017-05-18 21:35:45

标签: angular rxjs

考虑以下情况:

observerX => observableA <= observerY => observableB <= observerZ
  • 有两个 Observables A B )和三个观察者 X Y Z )。
  • 这些观察者和观察者中的每一个都在单独的(Angular)服务中。
  • 观察者 Y 同时观察到Observable A 和Observable B ,其中&#34; alive&#34;在申请期限内,即他们没有完成。
  • 当Observable A 触发事件时,Observer Y 会调用Observable B 服务上的函数,这会导致Observable B 触发事件。同样,当Observable B 触发事件时,Observer Y 会调用Observable A 服务上的函数,从而导致Observable 以触发事件。

前:观察员Y ......

svcA.obsA.subscribe(()=> {
    svcB.doSomething()
});

svcB.obsB.subscribe(()=> {
    svcA.doSomething()
});

正如您所看到的,所有Observer Y 正试图将服务 A 和服务 B 保持同步。

问题: 如上所述的设置导致无限的执行循环。我想到解决这个问题的一个想法是在每个订阅中设置一个标志,当设置该标志时,另一个订阅将忽略下一个事件。这不是一个合适的解决方案,因为下一个事件可能不一定是与Observer Y 调用doSomething()相对应的事件,但可能是由于Observer X Z 致电doSomething()

这个用例有优雅的解决方案吗?我这里有建筑问题吗?如果我对问题的描述不清楚,请告诉我。

JSFiddles:

2 个答案:

答案 0 :(得分:0)

好的,所以这个关系可以使用以下自动机建模(ObserverY只转发,因此可以忽略):

enter image description here

它将永远循环。 问题是你不能只使用一个通道来避免无限循环(即不检查消息是来自外部还是邻居(A / B))。

所以,你的选择:

  1. 将对象耦合在一起,这样他们就可以区分消息(A / B可以判断消息是否来自B / A)。

  2. 使用单独的渠道传递信息(我知道你可以使用Rx,但我可能错了)。

  3. 使用此hack:https://jsfiddle.net/6oz6mgLL/,它会添加单独的方法sync()和bool synced。对象没有耦合,但每个外部事件将花费您1次重复的方法调用(学习代码以了解原因)。

  4. 这不会出现在你的问题描述中,但是如果使用只保留一个项目的ReplaySubject并且仅在它改变时进行广播,那么3中的解决方案将无需额外调用即可顺利运行。我不知道你是否可以申请ReplaySubject

  5. 如果对象在概念级别上耦合,则可能无法始终保持代码中的解耦。

    希望至少有一点帮助。

答案 1 :(得分:0)

我认为您可以将thottletime运算符(https://www.learnrxjs.io/learn-rxjs/operators/filtering/throttletime)与较短的持续时间选择器结合使用,例如对于可观察的 A B 均为100ms。

obsA.pipe(throttleTime(100)).subscribe(val => obsB.next(val));
obsB.pipe(throttleTime(100)).subscribe(val => obsA.next(val));

假设第二个可观察物 A B 的发射小于100ms,则将忽略它们。