在Completablefuture和Observable之间转换

本文探讨了如何在Java 8的CompletableFuture和RxJava的Observable之间进行转换,同时保持其异步和事件驱动的特性。通过示例代码展示了CompletableFuture到Observable的转换以及Observable到CompletableFuture的转换,包括成功值和异常处理的情况。
摘要由CSDN通过智能技术生成

Java 8中的CompletableFuture<T>是对T类型的值将来将可用的承诺的高级抽象。 Observable<T>非常相似,但是它承诺将来会出现任意数量的项,从0到无穷大。 异步结果的这两种表示与仅使用一项即可使用Observable而不是CompletableFuture情况非常相似,反之亦然。 另一方面, CompletableFuture更专业,并且由于它现在是JDK的一部分,因此应该很快就会流行起来。 让我们用简短的文章来庆祝RxJava 1.0发行版,该文章展示了如何在两者之间进行转换而又不失去它们的异步和事件驱动性质。

CompletableFuture表示将来的一个值,因此将其变为Observable非常简单。 当Future以某个值完成时, Observable也将立即发出该值并关闭流:

class FuturesTest extends Specification {
 
    public static final String MSG = "Don't panic"
 
    def 'should convert completed Future to completed Observable'() {
        given:
            CompletableFuture<String> future = CompletableFuture.completedFuture("Abc")
 
        when:
            Observable<String> observable = Futures.toObservable(future)
 
        then:
            observable.toBlocking().toIterable().toList() == ["Abc"]
    }
 
    def 'should convert failed Future into Observable with failure'() {
        given:
            CompletableFuture<String> future = failedFuture(new IllegalStateException(MSG))
 
        when:
            Observable<String> observable = Futures.toObservable(future)
 
        then:
            observable
                    .onErrorReturn({ th -> th.message } as Func1)
                    .toBlocking()
                    .toIterable()
                    .toList() == [MSG]
    }  
 
    CompletableFuture failedFuture(Exception error) {
        CompletableFuture future = new CompletableFuture()
        future.completeExceptionally(error)
        return future
    }
 
}

尚未执行的 Futures.toObservable()第一个测试会将Future转换为Observable ,并确保正确传播值。 第二个测试创建了失败的Future ,将失败替换为异常的消息,并确保传播了异常。 实现要短得多:

public static <T> Observable<T> toObservable(CompletableFuture<T> future) {
    return Observable.create(subscriber ->
            future.whenComplete((result, error) -> {
                if (error != null) {
                    subscriber.onError(error);
                } else {
                    subscriber.onNext(result);
                    subscriber.onCompleted();
                }
            }));
}

注意: Observable.fromFuture()存在,但是我们想充分利用ComplatableFuture的异步运算符。

实际上,有两种将Observable转换为Future -创建CompletableFuture<List<T>>CompletableFuture<T> (如果我们假设Observable仅包含一项)。 让我们从前一种情况开始,用以下测试用例进行描述:

def 'should convert Observable with many items to Future of list'() {
    given:
        Observable<Integer> observable = Observable>just(1, 2, 3)
 
    when:
        CompletableFuture<List<Integer>> future = Futures>fromObservable(observable)
 
    then:
        future>get() == [1, 2, 3]
}
 
def 'should return failed Future when after few items exception was emitted'() {
    given:
        Observable<Integer> observable = Observable>just(1, 2, 3)
                >concatWith(Observable>error(new IllegalStateException(MSG)))
 
    when:
        Futures>fromObservable(observable)
 
    then:
        def e = thrown(Exception)
        e>message == MSG
}

显然,直到源Observable信号流结束, Future才完成。 因此, Observable.never()将永远不会完成包装Future ,而是使用空列表来完成它。 该实现更短,更甜蜜:

public static <T> CompletableFuture<List<T>> fromObservable(Observable<T> observable) {
    final CompletableFuture<List<T>> future = new CompletableFuture<>();
    observable
            .doOnError(future::completeExceptionally)
            .toList()
            .forEach(future::complete);
    return future;
}

关键是Observable.toList() ,它可以方便地从Observable<T>Observable<List<T>> 。 当源Observable<T>完成时,后者将发出List<T>类型的一项。

当我们知道CompletableFuture<T>将恰好返回一项时,就会发生上一次转换的特殊情况。 在这种情况下,我们可以将其直接转换为CompletableFuture<T> ,而不是仅包含一项的CompletableFuture<List<T>> 。 首先测试:

def 'should convert Observable with single item to Future'() {
    given:
        Observable<Integer> observable = Observable.just(1)
 
    when:
        CompletableFuture<Integer> future = Futures.fromSingleObservable(observable)
 
    then:
        future.get() == 1
}
 
def 'should create failed Future when Observable fails'() {
    given:
        Observable<String> observable = Observable.<String> error(new IllegalStateException(MSG))
 
    when:
        Futures.fromSingleObservable(observable)
 
    then:
        def e = thrown(Exception)
        e.message == MSG
}
 
def 'should fail when single Observable produces too many items'() {
    given:
        Observable<Integer> observable = Observable.just(1, 2)
 
    when:
        Futures.fromSingleObservable(observable)
 
    then:
        def e = thrown(Exception)
        e.message.contains("too many elements")
}

同样,实现非常简单并且几乎相同:

public static <T> CompletableFuture<T> fromSingleObservable(Observable<T> observable) {
    final CompletableFuture<T> future = new CompletableFuture<>();
    observable
        .doOnError(future::completeExceptionally)
        .single()
        .forEach(future::complete);
    return future;
}

上面的Helper方法还不够完善,但是,如果您需要在JDK 8和RxJava风格的异步计算之间进行转换,那么这篇文章应该足以帮助您入门。

翻译自: https://www.javacodegeeks.com/2014/12/converting-between-completablefuture-and-observable.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值