如何在另一个完成后创建一个Observable,并合并结果

时间:2017-05-24 14:55:01

标签: java rx-java

我有:

  • Observable<T1> a
  • Supplier<Observable<T2>> p
  • Function<T1, R> f
  • Function<T2, R> g

我想按如下方式对ap.get()进行排序:

  • 等待a完成,然后致电Observable<T2> b = p.get()
  • 使用ab
  • Rf的值映射到g类型
  • 将结果作为Observable<R>
  • 返回
  • 如果ab失败,结果应该会失败
  • 应在b完成后完成。

这是我到目前为止所尝试的内容(忽略fg):

public static <T> Observable<T> sequence(final Observable<? extends T> a, final Supplier<Observable<? extends T>> p) {

    final Subject<T> subject = PublishSubject.create();

    a.subscribe(
        subject::onNext,
        subject::onError,
        () -> {
            p.get().subscribe(
                subject::onNext,
                subject::onError,
                subject::onComplete);
        });

    return subject;
}

我该如何实现?

2 个答案:

答案 0 :(得分:1)

现在我没有IDE,所以我不确定这段代码是否实际编译。但这个想法是这样的:

a                               // your first observable
    .map(f::apply)              // map first result to R
    .flatMap(r1 -> p.get()      // "concat" second observable
        .map(g::apply)          // map result result to R
        .map(r2 -> {
            // some kind of operation between r1 and r2
        })
    )
    .subscribe(next -> {
        // do something with value
    }, error -> {
        // error from either observable
    }, () -> {
        // completed!
    });

如果f计算非常昂贵,并且您只想在第二个可观察量不会失败的情况下执行此操作,则可以将其更改为

a                               // your first observable
    .flatMap(r1 -> p.get()      // "concat" second observable
        .map(g::apply)          // map result result to R
        .map(r2 -> {
            R valueFromFirstObservable = f.apply(r1);
            // some kind of operation between r1 and r2
        })
    )
    .subscribe(next -> {
        // do something with value
    }, error -> {
        // error from either observable
    }, () -> {
        // completed!
    });

如果您需要第一个观察者在开始第二个观察之前完全完成,那么您需要使用第一个可以使用的所有项目toList()

a                               // your first observable
    .map(f::apply)              // map first result to R
    .toList()                   // by converting to a List you are forcing the observable to finish before continuing
    .flatMap(r1Items -> p.get() // "concat" second observable
        .map(g::apply)          // map result result to R
        .toList()               // wait until p.get() finishes. Remove this line if you want to emit for all values
        .map(r2Items -> {
            // Some kind of operation between r1Items and r2Items 
            // Beware that now they are not of type R but List<R>
        })
    )
    .subscribe(next -> {
        // do something with value
    }, error -> {
        // error from either observable
    }, () -> {
        // completed!
    });

答案 1 :(得分:0)

public static <T> Observable<T> sequence(final Observable<? extends T> a, final Supplier<Observable<? extends T>> f) {
    return a.publish(i -> Observable.merge(
        i, 
        i.lastOrError().flatMapObservable(f::apply));
}