我有以下代码:
final Observable<String> a = Observable.just("a1", "a2");
final Observable<String> b = Observable.just("b1");
final Observable<String> c = Observable.combineLatest(a, b, (first, second) -> first + second);
c.subscribe(res -> System.out.println(res));
预期产量是多少?我原以为
a1b1
a2b1
但实际输出是
a2b1
这有意义吗?生成预期序列的正确运算符是什么?
答案 0 :(得分:1)
好问题!似乎可能是竞争条件。在两个来源都已发出之前,combineLatest
不会输出任何内容,并且在b
生成其输出时,a
已经转移到第二个项目。在具有时间间隔的异步事件的“真实世界”应用程序中,您可能会获得所需的行为。
如果你能忍受等待,解决办法就是延迟a
的输出。通过更多的工作,您可以延迟第一个输出(请参阅delay
运算符的各种重载)。我还注意到有一个操作符delaySubscription
可能会解决问题(延迟订阅a
直到b
发出一些东西)。我敢肯定还有其他的,或许更好的解决方案(我还在学习自己)。
答案 1 :(得分:1)
正如运营商的名称所暗示的那样,它结合了每个来源的最新价值。如果源是同步的或非常快,这可能意味着一个或多个源将运行完成,操作员将只记住每个源的最后一个值。您必须通过某种方式交错源值,例如在项目之间具有足够时间的异步源,并避免多个源项目的紧密重叠。
预期的序列可以通过几种方式生成,具体取决于您的初衷。例如,如果您想要所有交叉组合,请使用flatMap
:
a.flatMap(aValue -> b, (aValue, bValue) -> first + second)
.subscribe(System.out::println);
如果b
重新创建成本高昂,请将其缓存:
Observable<String> cachedB = b.cache();
a.flatMap(aValue -> cachedB, (aValue, bValue) -> first + second)
.subscribe(System.out::println);