RXJava - combineLatest不会丢失任何结果

时间:2016-09-07 17:53:21

标签: java rx-java

我想要组合两个observable,一个发出n个项目,另一个只发生1个。

combineLatest将等到两个observable都至少发出一个项目,然后组合最新发出的项目,直到两个observable都完成。请按照时间顺序考虑:

  • 可观察的A - >发出结果A1
  • 可观察的A - >发出结果A2
  • 可观察的B - >发出结果B1

combineLatest只会将可观察1的结果2与可观察2的结果1结合起来(可以很容易地在这里测试:http://rxmarbles.com/#combineLatest)。

我需要什么

我需要组合两个可观察对象的所有项目,无论哪个更快。我怎么能这样做?

结果应该是(始终独立于哪个观察者首先开始发射物品!):

  • A1与B1结合
  • A2与B1结合

2 个答案:

答案 0 :(得分:1)

旧问题,但我遇到了同样的问题。这是我的目的。首先,非工作版本:

    Observable<Integer> emitsMany = Observable.range( 1, 10 )
            .concatMap( i -> Observable.just( i ).delay( 1, TimeUnit.SECONDS ))
            .doOnNext( i -> System.out.println( "produced " + i ));

    Observable<Boolean> emitsOne = Observable.just( true )
            .delay( 3, TimeUnit.SECONDS )
            .doOnNext( b -> System.out.println( "produced " + b ));

    Observable.combineLatest(
            emitsMany, emitsOne,
            ( i, b ) -> "consumed " + i + " " + b )
    .blockingSubscribe( System.out::println );

果然,emitsMany的前几对排放被丢弃:

produced 1
produced 2
produced 3
produced true
consumed 3 true
produced 4
consumed 4 true
. . .

我认为这是解决方法。首先,我们需要将emitsOne包装到可以继续返回先前观察到的值而不会延迟的内容中。我不知道要执行此操作的操作员,但是BehaviorSubject可以完成这项工作。

接下来,我们可以将concatMap与嵌套的take(1) Observable一起使用:

    Observable<Integer> emitsMany = Observable.range( 1, 10 )
            .concatMap( i -> Observable.just( i ).delay( 1, TimeUnit.SECONDS ))
            .doOnNext( i -> System.out.println( "produced " + i ));

    Observable<Boolean> emitsOne = Observable.just( true )
            .delay( 3, TimeUnit.SECONDS )
            .doOnNext( b -> System.out.println( "produced " + b ));

    BehaviorSubject<Boolean> emitsOneSubject = BehaviorSubject.create();
    emitsOne.subscribe( emitsOneSubject::onNext );

    emitsMany.concatMap( i -> emitsOneSubject
            .take( 1 )
            .map( b -> "consumed " + i + " " + b ))
    .blockingSubscribe( System.out::println );

我们现在获得了所有组合:

produced 1
produced 2
produced true
consumed 1 true
consumed 2 true
produced 3
consumed 3 true
produced 4
consumed 4 true
produced 5
consumed 5 true
produced 6
consumed 6 true
produced 7
consumed 7 true
produced 8
consumed 8 true
produced 9
consumed 9 true
produced 10
consumed 10 true

答案 1 :(得分:0)

请注意,这是未经测试的:

从可观察序列a创建ReplaySubject。对于按序列b发出的每个值,将该值与重播主题组合以创建新的Pair <A, B>可观察值。将这些可观察对象平面映射并将其作为结果返回。

public static <A, B> Observable<Pair<A, B>> permutation(
    Observable<A> observableA, 
    Observable<B> observableB, 
) {
    ReplaySubject<A> subjectA = ReplaySubject.create();
    observableA.subscribe(subjectA::onNext);
    return observableB.flatMap(b -> subjectA.map(a -> Pair.of(a, b)));
}