На самом деле это не имеет значения, потому что Rx Java пытается поймать и ретранслировать все Throwables
ПОДХОД 1 - выбросить новое 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 нижестоящему подписчику.
ПОДХОД 2 - return Single.error (...) (io.reactivex.internal.operators.single .SingleError)
Single # error
@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 выдает данный Throwable по подписке через # onError
Когда значение передается в 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 возвращает ошибку Single #, которая генерирует Throwable через #onError. Данная ошибка #onError будет делегирована нижестоящему подписчику через onError.
С точки зрения производительности один может быть быстрее другого, но это должно быть измерено, чтобы получить точное изображение. При возврате ошибки Single # выполняется больше распределений и больше методов в стеке (subscribeActual). С другой стороны, при броске метательного предмета его нужно поймать и направить.