RxJava - 使用 Single.Error / Observable.error 与抛出异常
RxJava - Using Single.Error / Observable.error vs throwing exception
我最近开始在我的一个项目中使用 RxJava2,目前我正致力于在其中实现错误处理。
我在下面编写了一个模拟 class,其中我最初在将错误包装在自定义异常中后抛出错误。但是,我在 Whosebug 和其他站点上遇到的一些错误处理示例使用了 Single.error
。
我使用了这两种方法,它们导致我的订阅者 onError
方法被调用时出现 / by zero
异常。我没有注意到两者之间有任何区别。
关于 Error Handling and Error Handling Operators along with a lot of other articles on how to handle the exception after it is thrown. But the information in the javadoc for Single.error and Observable.error 的综合文档非常少。
使用 Single.error
或 Observable.error
是否比仅抛出异常有优势?我们什么时候选择一种方法而不是另一种方法?
public class Test {
public static void main(String[] args){
Single.just(1)
.flatMap(x -> externalMethod(x))
.subscribe(
s -> System.out.println("Success : " + s),
e -> System.out.println("Error : "+e)
);
}
public static Single<Integer> externalMethod(int x){
int result = 0;
try{
/* Some database / time consuming logic */
result = x % 0;
}
catch (Exception e){
throw new CustomException(e.getMessage()); // --> APPROACH 1
OR
return Single.error(new CustomException(e.getMessage())); // --> APPROACH 2
}
return Single.just(result);
}
}
其实没关系,因为 RxJava 试图捕获并中继所有 Throwables
APPROACH 1 -- throw new CustomException();
(io.reactivex.internal.operators.single.SingleFlatMap)
@Override
public void onSuccess(T value) {
SingleSource<? extends R> o;
try {
o = ObjectHelper.requireNonNull(mapper.apply(value), "The single returned by the mapper is null");
} catch (Throwable e) {
Exceptions.throwIfFatal(e);
downstream.onError(e);
return;
}
if (!isDisposed()) {
o.subscribe(new FlatMapSingleObserver<R>(this, downstream));
}
}
你在这里看到,来自 flatMap 的给定映射器是通过 try-catch 调用的。如果映射器抛出一个 Throwable,Throwable 将通过 onError 转发给下游订阅者。
APPROACH 2 -- return Single.error(...)
(io.reactivex.internal.operators.single.SingleError)
单#错误
@Override
protected void subscribeActual(SingleObserver<? super T> observer) {
Throwable error;
try {
error = ObjectHelper.requireNonNull(errorSupplier.call(), "Callable returned null throwable. Null values are generally not allowed in 2.x operators and sources.");
} catch (Throwable e) {
Exceptions.throwIfFatal(e);
error = e;
}
EmptyDisposable.error(error, observer);
}
public static void error(Throwable e, SingleObserver<?> observer) {
observer.onSubscribe(INSTANCE);
observer.onError(e);
}
Single#error 通过#onError
在订阅时发出给定的 Throwable
当向 Single#flatMap 发送值时,将应用映射器并打开订阅,并从映射器返回值。
(io.reactivex.internal.operators.single.SingleFlatMap.SingleFlatMapCallback.FlatMapSingleObserver)
@Override
public void onSubscribe(final Disposable d) {
DisposableHelper.replace(parent, d);
}
@Override
public void onError(final Throwable e) {
downstream.onError(e);
}
返回的 Single returns 一个 Single#error,它通过 #onError 发出一个 Throwable。给定#onError 将通过onError 委托给下游订阅者。
在性能方面,一个可能比另一个更快,但这必须经过测量才能获得准确的图像。返回 Single#error 会进行更多分配,并在 Stack (subscribeActual) 上有更多方法。另一方面,当抛出一个 Throwable 时,它必须被抓住并处理。
因此在我看来,无论您使用一个还是另一个,实际上都没有关系。
我最近开始在我的一个项目中使用 RxJava2,目前我正致力于在其中实现错误处理。
我在下面编写了一个模拟 class,其中我最初在将错误包装在自定义异常中后抛出错误。但是,我在 Whosebug 和其他站点上遇到的一些错误处理示例使用了 Single.error
。
我使用了这两种方法,它们导致我的订阅者 onError
方法被调用时出现 / by zero
异常。我没有注意到两者之间有任何区别。
关于 Error Handling and Error Handling Operators along with a lot of other articles on how to handle the exception after it is thrown. But the information in the javadoc for Single.error and Observable.error 的综合文档非常少。
使用 Single.error
或 Observable.error
是否比仅抛出异常有优势?我们什么时候选择一种方法而不是另一种方法?
public class Test {
public static void main(String[] args){
Single.just(1)
.flatMap(x -> externalMethod(x))
.subscribe(
s -> System.out.println("Success : " + s),
e -> System.out.println("Error : "+e)
);
}
public static Single<Integer> externalMethod(int x){
int result = 0;
try{
/* Some database / time consuming logic */
result = x % 0;
}
catch (Exception e){
throw new CustomException(e.getMessage()); // --> APPROACH 1
OR
return Single.error(new CustomException(e.getMessage())); // --> APPROACH 2
}
return Single.just(result);
}
}
其实没关系,因为 RxJava 试图捕获并中继所有 Throwables
APPROACH 1 -- throw new CustomException(); (io.reactivex.internal.operators.single.SingleFlatMap)
@Override
public void onSuccess(T value) {
SingleSource<? extends R> o;
try {
o = ObjectHelper.requireNonNull(mapper.apply(value), "The single returned by the mapper is null");
} catch (Throwable e) {
Exceptions.throwIfFatal(e);
downstream.onError(e);
return;
}
if (!isDisposed()) {
o.subscribe(new FlatMapSingleObserver<R>(this, downstream));
}
}
你在这里看到,来自 flatMap 的给定映射器是通过 try-catch 调用的。如果映射器抛出一个 Throwable,Throwable 将通过 onError 转发给下游订阅者。
APPROACH 2 -- return Single.error(...) (io.reactivex.internal.operators.single.SingleError)
单#错误
@Override
protected void subscribeActual(SingleObserver<? super T> observer) {
Throwable error;
try {
error = ObjectHelper.requireNonNull(errorSupplier.call(), "Callable returned null throwable. Null values are generally not allowed in 2.x operators and sources.");
} catch (Throwable e) {
Exceptions.throwIfFatal(e);
error = e;
}
EmptyDisposable.error(error, observer);
}
public static void error(Throwable e, SingleObserver<?> observer) {
observer.onSubscribe(INSTANCE);
observer.onError(e);
}
Single#error 通过#onError
在订阅时发出给定的 Throwable当向 Single#flatMap 发送值时,将应用映射器并打开订阅,并从映射器返回值。
(io.reactivex.internal.operators.single.SingleFlatMap.SingleFlatMapCallback.FlatMapSingleObserver)
@Override
public void onSubscribe(final Disposable d) {
DisposableHelper.replace(parent, d);
}
@Override
public void onError(final Throwable e) {
downstream.onError(e);
}
返回的 Single returns 一个 Single#error,它通过 #onError 发出一个 Throwable。给定#onError 将通过onError 委托给下游订阅者。
在性能方面,一个可能比另一个更快,但这必须经过测量才能获得准确的图像。返回 Single#error 会进行更多分配,并在 Stack (subscribeActual) 上有更多方法。另一方面,当抛出一个 Throwable 时,它必须被抓住并处理。
因此在我看来,无论您使用一个还是另一个,实际上都没有关系。