我正在尝试使用RxJava和Java 8的CompletableFuture类 并且不太了解如何处理超时条件。
import static net.javacrumbs.futureconverter.java8rx.FutureConverter.toObservable;
// ...
Observable<String> doSomethingSlowly() {
CompletableFuture<PaymentResult> task = CompletableFuture.supplyAsync(() -> {
// this call may be very slow - if it takes too long,
// we want to time out and cancel it.
return processor.slowExternalCall();
});
return toObservable(task);
}
// ...
doSomethingSlowly()
.single()
.timeout(3, TimeUnit.SECONDS, Observable.just("timeout"));
这基本上有效(如果达到超时三秒,&#34;超时&#34;已发布)。然而,我还想取消我在Observable
中包含的未来任务 - 是否可能采用以RxJava为中心的方法?
我知道一个选项是使用task.get(3, TimeUnit.SECONDS)
来处理超时,但我想知道是否可以在RxJava中执行所有任务处理。
答案 0 :(得分:10)
是的,你可以这样做。您可以向Subscription
添加Subscriber
。
这允许您收听取消订阅,如果您明确调用subscribe().unsubscribe()
或Observable
成功完成或出错,则会发生取消订阅。
如果您在未来完成之前看到取消订阅,则可以假定它是明确的unsubscribe
或超时。
public class FutureTest {
public static void main(String[] args) throws IOException {
doSomethingSlowly()
.timeout(1, TimeUnit.SECONDS, Observable.just("timeout"))
.subscribe(System.out::println);
System.in.read(); // keep process alive
}
private static Observable<String> doSomethingSlowly() {
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
}
return "Something";
});
return toObservable(future);
}
private static <T> Observable<T> toObservable(CompletableFuture<T> future) {
return Observable.create(subscriber -> {
subscriber.add(new Subscription() {
private boolean unsubscribed = false;
@Override
public void unsubscribe() {
if (!future.isDone()){
future.cancel(true);
}
unsubscribed = true;
}
@Override
public boolean isUnsubscribed() {
return unsubscribed;
}
});
future.thenAccept(value -> {
if (!subscriber.isUnsubscribed()){
subscriber.onNext(value);
subscriber.onCompleted();
}
}).exceptionally(throwable -> {
if (!subscriber.isUnsubscribed()) {
subscriber.onError(throwable);
}
return null;
});
});
}
}