以递归方式将Rx选项组合成Obserbles

比方说,我有一个名为s_0Single ,它可以从T类型发出一个元素t_0 ,也可以失败(在某些语言中,这可能是Single<T> )。 那是:

 s_0: -- t_0 // Success OR s_0: -- X // Failure 

T类型的实例有一个next()方法,它返回T类型的一个可选的SingleKotlin中Single<T>? )。 这种行为导致一个能够发射一个T实例链的Single实例链,其中每个单独的s_i可以发出一个能够返回下一个单独的s_i+1的元素t_i+1 ,这将发出一个元素t_i+1等等,直到最后一个元素t_n-1没有返回单个或任何单数失败:

 s_0: -- t_0 ↓ s_1: -- t_1 ↓ s_2: -- t_2 ... ↓ s_n-1: -- t_n-1 ↓ null OR s_0: -- t_0 ↓ s_1: -- t_1 ↓ s_2: -- t_2 ... ↓ s_i: -- X 

我正在寻找一种优雅的方式来获得一个T型的Observable o ,它能够在链上没有更多的单链或者失败的情况下成功地从s_0开始,

 o: -- t_0 -- t_1 -- t_2 -- ... -- t_n-1 --o // Success OR o: -- t_0 -- t_1 -- t_2 -- ... --X // Failure 

通过优雅 ,我的意思是这样简单(在科特林 ):

 // Get single somehow (out of the scope of this question) val s0: Single<T> = provideSingle() // Get observable val o: Observable<T> = s0.chain() // Define extension method fun Single<T>.chain(): Observable<T> { /* Implement here */ } // Element interface interface T { fun next(): Single<T>? } 

这是什么适用性?

当使用分页的REST API时,可以发现这种情况,其中可以使用Single实例来检索单个页面,从而可以提供能够发送后续页面的Single实例。

我没有测试过这个,但是基于我前一段时间编写的解决方案,我把它翻译成Kotlin的类似的分页问题

 fun Single<T>.chain(): Observable<T> = toObservable() .concatWith { it.next()?.chain() ?: Observable.empty() } 

获得“递归”链接的关键是concatWith运算符递归调用chain方法

 public class Q44535765 { public static void main(String[] args) { Maybe<Element> first = get(); first.toObservable() .compose(o -> chain(o)) .doOnError(e -> System.out.println(e)) .subscribe( e -> System.out.println(e), e -> System.out.println("fail"), () -> System.out.println("complete")); } static Maybe<Element> get() { return Maybe.just( () -> If.<Maybe<Element>> that(Math.random() > 0.1) .tobe(() -> get()) .orbe(() -> If.<Maybe<Element>> that(Math.random() > 0.5) .tobe(() -> Maybe.empty()) .orbe(() -> null) .result()) .result()); } static Observable<Element> chain(Observable<Element> s) { return s.concatMap( e -> Observable.just(e) .concatWith(e.next() .toObservable() .compose(o -> chain(o)))); } interface Element { Maybe<Element> next(); } } 

If是我的util类,你可以通过if...else...