如果我有一个Observalbe:
List<Integer> ints = Lists.newArrayList(1, 2, 0, 3, 4);
Observable<Integer> o1 = Observable.from(ints);
我想生成另一个observable,除以12:
Observable<Integer> o2 = o1.map(i -> 12/i);
o2.subscribe(
v -> logger.info ("Subscriber value {}", v) ,
t -> logger.error("Subscriber onError {} : {}", t.getClass() , t.getMessage())
);
很明显它会出错,并在遇到'0'时停止:
RxTest - Subscriber value 12
RxTest - Subscriber value 6
RxTest - Subscriber onError class java.lang.ArithmeticException : / by zero
但是,如果我希望Observer(o2)跳过异常怎么办?
我查看了RxJava关于error handling的文档,没有办法跳过错误。 onErrorResumeNext()
和onExceptionResumeNext()
需要备份/后备 Observable
,这不是我想要的。 onErrorReturn
需要指定返回值。
所有三种错误处理方法都无法恢复原始观察者。例如:
Observable<Integer> o2 = o1.map(i -> 12/i)
.onErrorReturn(t -> 0);
打印:
RxTest - Subscriber value 12
RxTest - Subscriber value 6
RxTest - Subscriber value 0
不打印其余的12/3和12/4
唯一的解决方案似乎是map
函数中的继电器:
Observable<Integer> o2 = o1.map(i -> {
try {
return Optional.of(12/i);
} catch (ArithmeticException e) {
return Optional.empty();
}
}).filter(Optional::isPresent)
.map(o -> (Integer) o.get());
它有效,但很麻烦。我想知道在操纵RuntimeException
时是否有任何方法可以轻松跳过任何Observable
(例如map
)
以上是关于在Observable
中跳过例外情况。以下是关于在Subscriber
:
情况是一样的:
List<Integer> ints = Lists.newArrayList(1, 2, 0 , 3 , 4);
Observable<Integer> o1 = Observable.from(ints);
o1.subscribe(
i -> logger.info("12 / {} = {}", i, 12 / i),
t -> logger.error("{} : {}", t.getClass() , t.getMessage()),
() -> logger.info("onCompleted")
);
打印出来:
RxTest - 12 / 1 = 12
RxTest - 12 / 2 = 6
RxTest - class java.lang.ArithmeticException : / by zero
当onNext
发生异常时,它会触发onError
,而不会回复Observable
中的任何数据。如果我希望订阅者吞下异常,我必须尝试捕获ArithmeticException
中的onNext()
。有没有更清洁的解决方案?
似乎当Subscriber
面临onNext()
中无法在(onNext
)内处理的错误时,它会停止,对吧?这是一个好的设计吗?
答案 0 :(得分:5)
Observable.just(1, 2, 3, 0, 4)
.flatMap(i -> Observable.defer(() -> Observable.just(12 / i))
.onErrorResumeNext(Observable.just(0)));
这是一种方法,但请记住,RxJava假设错误是真正无法解决的(您可以预期值为0)。另一方面,如果你想忽略除以0异常,你可能应该在除法之前过滤/映射你的值。
答案 1 :(得分:1)
试试这种方式。
Observable<Integer> o2 = o1.map(i -> 12/i).onErrorFlatMap(e -> Observable.empty());
在上面的代码中,错误事件被空流替换,原始流正在恢复。因此会跳过错误。
答案 2 :(得分:0)
import rx.lang.scala._
import scala.concurrent.duration.DurationDouble
import scala.util.{Failure, Success, Try}
val o1 = List(1, 2, 3, 0, 4) toObservable
val o2 = List(1, 2, 3, 4, 5) toObservable
val o3 = o1 zip o2 map {case (i1, i2) => i2 / i1 } // this will trigger a division by 0 error
val o4 = o3 lift {
subscriber: Subscriber[Try[Int]] => new Subscriber[Int](subscriber) {
override def onNext(v: Int) {
if (!subscriber.isUnsubscribed)
subscriber.onNext(Success(v))
}
override def onError(e: Throwable) {
if (!subscriber.isUnsubscribed)
subscriber.onNext(Failure(e))
}
override def onCompleted() {
if (!subscriber.isUnsubscribed)
subscriber.onCompleted()
}
}
}
o4 subscribe(println(_))