考虑以下情况:
observerX => observableA <= observerY => observableB <= observerZ
前:观察员Y ......
svcA.obsA.subscribe(()=> {
svcB.doSomething()
});
svcB.obsB.subscribe(()=> {
svcA.doSomething()
});
正如您所看到的,所有Observer Y 正试图将服务 A 和服务 B 保持同步。
问题:
如上所述的设置导致无限的执行循环。我想到解决这个问题的一个想法是在每个订阅中设置一个标志,当设置该标志时,另一个订阅将忽略下一个事件。这不是一个合适的解决方案,因为下一个事件可能不一定是与Observer Y 调用doSomething()
相对应的事件,但可能是由于Observer X 或 Z 致电doSomething()
。
这个用例有优雅的解决方案吗?我这里有建筑问题吗?如果我对问题的描述不清楚,请告诉我。
JSFiddles:
答案 0 :(得分:0)
好的,所以这个关系可以使用以下自动机建模(ObserverY只转发,因此可以忽略):
它将永远循环。 问题是你不能只使用一个通道来避免无限循环(即不检查消息是来自外部还是邻居(A / B))。
所以,你的选择:
将对象耦合在一起,这样他们就可以区分消息(A / B可以判断消息是否来自B / A)。
使用单独的渠道传递信息(我知道你可以使用Rx,但我可能错了)。
使用此hack:https://jsfiddle.net/6oz6mgLL/,它会添加单独的方法sync()
和bool synced
。对象没有耦合,但每个外部事件将花费您1次重复的方法调用(学习代码以了解原因)。
这不会出现在你的问题描述中,但是如果使用只保留一个项目的ReplaySubject
并且仅在它改变时进行广播,那么3中的解决方案将无需额外调用即可顺利运行。我不知道你是否可以申请ReplaySubject
。
如果对象在概念级别上耦合,则可能无法始终保持代码中的解耦。
希望至少有一点帮助。
答案 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,则将忽略它们。