RxJava:combineLatest的行为

时间:2018-02-20 15:36:41

标签: java rx-java2 reactive combinelatest

我有以下代码:

    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

这有意义吗?生成预期序列的正确运算符是什么?

2 个答案:

答案 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);