RxJava Error Handling Operators
RxJava Error Handling Operators
簡介
RxJava提供了一些操作函式去處理錯誤相關的情景,使用這些函式可以:
- 吞掉這個錯誤,切換到一個備用的Observable繼續發射資料
- 吞掉這個錯誤然後發射預設值
- 吞掉這個錯誤並立即嘗試重啟這個Observable
- 吞掉這個錯誤,在等待一段時間後重啟這個Observable
相關處理函式
處理錯誤相關的操作函式包括:
onErrorReturn
public final Observable<T> onErrorReturn(Func1<java.lang.Throwable,? extends T> resumeFunction)
Instructs an Observable to emit an item (returned by a specified function) rather than invoking onError if it encounters an error.
一般出錯時,會呼叫onError,然後結束.使用onErrorReturn,onError不會呼叫,而是傳送onErrorReturn裡面提供的值,然後onCompleted會被呼叫. 注意,緊隨其後onCompleted會呼叫.
例子:
Observable<String> observable = Observable.create(new OnSubscribe<String>(){
@Override
public void call(Subscriber<? super String> arg0) {
arg0.onNext("a1");
arg0.onNext("a2");
arg0.onError(new Exception("testErrorReturn mock error"));
}
});
observable.onErrorReturn(new Func1<Throwable, String>() {
@Override
public String call(Throwable arg0) {
Utils.println("onErrorReturn call");
return "aError";
}
})
.subscribe(new Subscriber<String>() {
@Override
public void onCompleted() {
Utils.println("onCompleted");
}
@Override
public void onError(Throwable arg0) {
Utils.println("onError");
}
@Override
public void onNext(String arg0) {
Utils.println("onResult:"+arg0);
}
});
輸出:
onResult:a1
onResult:a2
onErrorReturn call
onResult:aError
onCompleted
onErrorResumeNext
宣告:
public final Observable<T> onErrorResumeNext(final Observable<? extends T> resumeSequence) {
public final Observable<T> onErrorResumeNext(final Func1<Throwable, ? extends Observable<? extends T>> resumeFunction);
如果原Observable發生錯誤時,不呼叫onError,而是使用一個新的Observable,呼叫它的call函式(其實就是訂閱它),裡面onNext的值回傳到subscriber,如果有調onCompleted,則subscriber會收到,如果沒有則不會收到. 即後續的行為由新的Observable決定了.
上面兩個函式的區別是第一個始終提供一個Observable,而第二個可以根據不同的Throwable提供不同的Observable.
例子:
Observable<String> observable = Observable.create(new OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> arg0) {
arg0.onNext("value1");
arg0.onNext("value2");
arg0.onNext("value3");
arg0.onError(new Exception("mock testErrorResumeNext exception"));
arg0.onNext("value4");
}
});
Observable<String> resumeObservable = Observable.create(new OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> arg0) {
arg0.onNext("valueMock1");
arg0.onNext("valueMock2");
}
});
observable.onErrorResumeNext(resumeObservable).subscribe(getSubscriber());
輸出:
onResult:value1
onResult:value2
onResult:value3
onResult:valueMock1
onResult:valueMock2
如果resumeObservable呼叫onCompleted,則onCompleted會被呼叫.
onExceptionResumeNext
public final Observable<T> onExceptionResumeNext(final Observable<? extends T> resumeSequence);
Instructs an Observable to pass control to another Observable rather than invoking Observer#onError if it encounters an Exception.
*** 和onErrorResumeNext類似,區別是onErrorResumeNext是針對onError的throwable,而onExceptionResumeNext僅僅是針對onError裡的型別是Exception. ***
retry
if a source Observable emits an error, resubscribe to it in the hopes that it will complete without error.
如果Observable.onError呼叫,即發射錯誤,會重新訂閱原來的Obserable,即重新觸發Observable,也就是從新調它的call函式.這種方式資料會重複.
- public final Observable<T> retry():
無限重試,直到成功. - public final Observable<T> retry(final long count):
指定次數重試,超過指定次數還沒成功,則subscriber.onError會被呼叫. - public final Observable<T> retry(Func2<Integer, Throwable, Boolean> predicate):
傳入一個Fun2,裡面有兩個入參,一個表示目前引數的次數,另一個就是Observable.onError裡的型別,返回值true表示繼續重試,false表示不重試,Subscriber.onError會被呼叫.
也就是說只要Observable.onError被呼叫後,會呼叫Func2去判斷是否要重試,Integer表示詢問重試的次數,從1開始.
retry(count)例子:
Observable<String> observable = Observable.create(new OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> arg0) {
arg0.onNext("value1");
arg0.onNext("value2");
arg0.onNext("value3");
arg0.onError(new Exception("mock testRetryCount exception"));
arg0.onNext("value4");
}
});
observable.retry(1).subscribe(getSubscriber());
輸出:
onResult:value1
onResult:value2
onResult:value3
onResult:value1
onResult:value2
onResult:value3
onError
從上面可以看出,重試了一次,後面不重試,Subscriber.onError被呼叫.另外由於重試,資料重複了.
retry(Func2)例子:
Observable<String> observable = Observable.create(new OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> arg0) {
arg0.onNext("value1");
arg0.onNext("value2");
arg0.onNext("value3");
arg0.onError(new Exception("mock testRetryFunc2 exception"));
arg0.onNext("value4");
}
});
observable.retry(new Func2<Integer, Throwable, Boolean>() {
@Override
public Boolean call(Integer arg0, Throwable arg1) {
Utils.println("testRetryFunc2 func2::call time:"+arg0.intValue());
return (arg0.intValue()>1)?false:true;
}
})
.subscribe(getSubscriber());
輸出:
onResult:value1
onResult:value2
onResult:value3
testRetryFunc2 func2::call time:1
onResult:value1
onResult:value2
onResult:value3
testRetryFunc2 func2::call time:2
onError
Integer從1開始,第一次重試,第二次返回false所以就不重試了,直接onError了.
retryWhen
public final Observable<T> retryWhen(final Func1<? super Observable<? extends Throwable>, ? extends Observable<?>> notificationHandler);
public final Observable<T> retryWhen(final Func1<? super Observable<? extends Throwable>, ? extends Observable<?>> notificationHandler, Scheduler scheduler);
if a source Observable emits an error, pass that error to another Observable to determine whether to resubscribe to the source
retryWhen的輸入引數是Func1,接受一個輸入Observable<Throwable>, 返回輸出引數Observable<?>。
返回的Observable<?>所要傳送的事件決定了重試是否會發生:
- 如果傳送的是onCompleted或者onError事件,將不會觸發重訂閱。
- 如果它傳送onNext事件,則觸發重訂閱(不管onNext實際上是什麼事件)。
這就是為什麼使用了萬用字元作為泛型型別:這僅僅是個通知(next, error或者completed),一個很重要的通知而已。
*** 可以理解為如果原Observable.onError發生, 如果Func1返回的Observable<?>的onNext被呼叫,則重新訂閱原來的Observable重試,否則不重試.***
輸入的Observable(即Func1裡Observable<?extends Throwable>)必須作為輸出Observable(即Func1的返回值)的源。我們必須對Observable<Throwable>做出反應,然後基於它傳送事件;不能只返回一個通用泛型流。
原Observable每次一呼叫onError(Throwable),Observable<Throwable>都會被作為輸入傳入方法中。換句話說就是,它的每一次呼叫我們都需要決定是否需要重訂閱。
下面的例子會重試:
source.retryWhen(new Func1<Observable<? extends Throwable>, Observable<?>>() {
@Override public Observable<?> call(Observable<? extends Throwable> errors) {
return errors.flatMap(new Func1<Throwable, Observable<?>>() {
@Override public Observable<?> call(Throwable error) {
return Observable.timer(5, TimeUnit.SECONDS);
}
});
}
})
總結:
- onErrorReturn,吞掉錯誤,提供一個預設的返回值.
- onErrorResumeNext,吞掉錯誤,提供一個預設的Observable繼續傳送資料.
- onExceptionResumeNext,和onErrorResumeNext類似,區別是onErrorResumeNext是針對onError的throwable,而onExceptionResumeNext僅僅是針對onError裡的型別是Exception.
- retry,吞掉錯誤,按條件重新訂閱重試
- retryWhen,吞掉錯誤,由另外一個提供的Observable的行為決定是否重試,如果onNext被呼叫,則重新訂閱重試,onError或者onComplete被呼叫,則不重試.
RxJava特有的異常
CompositeException:
表示發生了多個異常。你可以使用異常的 getExceptions() 方法獲取單獨的異常。MissingBackpressureException:
表示一個訂閱者或者操作符試圖對一個不支援反壓操作的Observable應用該操作。可以參考 [[Backpressure]] 查詢針對沒有實現反壓操作的Observable的解決辦法。OnErrorFailedException:
表示Observable嘗試呼叫觀察者的 onError() 方法,但是那個方法自己丟擲了異常。OnErrorNotImplementedException:
表示一個Observable嘗試呼叫它的觀察者的onError() 方法,但是那個方法不存在。有多種方法可以消除這個錯誤:可以調整Observable使它不會到達這個錯誤條件,也可以在觀察者中實現一個onError 處理器, 或者使用其它的操作符在錯誤到達之前攔截這個 onError 通知。OnErrorThrowable:
觀察者們可以用這種形式傳遞異常給它們的觀察者們的 onError() 方法。相比標準的Throwable,這種Throwable包含更多的資訊:錯誤本身和在錯誤發生時Observable的內部狀態。
...
...
Reference
相關文章
- [Bash] Error handlingError
- [Vue Router] Error Handling and 404sVueError
- 【譯】 WebSocket 協議第八章——錯誤處理(Error Handling)Web協議Error
- ncnn operatorsCNN
- Multi-path handling for asmASM
- Netty series: handling CORS in nettyNettyCORS
- Handling duplicate form submission in Spring MVCORMSpringMVC
- [Typescript] Handling a Truly Empty Object in TypeScriptTypeScriptObject
- [LeetCode] 282. Expression Add OperatorsLeetCodeExpress
- VMware vSphere:Skills for Operators培訓
- Task03 : Data Types and Operators
- RxJS學習之路四(Operators(1))JS
- 3.0 常見operators運算元
- SAP Fiori 的附件處理(Attachment handling)
- 不要打破鏈式呼叫!一個極低成本的RxJava全域性Error處理方案RxJavaError
- 第三週--20200314--Handling NULL Values in PostgreSQLNullSQL
- RxJava小考題 -- Rxjava原始碼分析(一)RxJava原始碼
- RxJava梳理RxJava
- Retrofit + RxJavaRxJava
- 移植Rxjs中部分常用operators到陣列JS陣列
- 30 天精通 RxJS (15):Observable Operators - distinct, distinctUntilChangedJS
- 30 天精通 RxJS (17):Observable Operators - switch, mergeAll, concatAllJS
- presto官網閱讀記錄: Functions and Operators 部分RESTFunction
- Rxjava深入理解之自己動手編寫RxjavaRxJava
- 大話RxJava:一、初識RxJava與基本運用RxJava
- 大話RxJava:三、RxJava的中級使用方法RxJava
- 30 天精通 RxJS (16):Observable Operators - catch, retry, retryWhen, repeatJS
- 關於 RxJava 最友好的文章—— RxJava 2.0 全新來襲RxJava
- RxJava_distinct&distinctUntilChangedRxJava
- RxJava 合併操作RxJava
- RxJava快速入門RxJava
- SAP cross distribution chain status在Fiori應用中的draft handlingROSAIRaft
- Operators和 自定義控制器(Custom Controllers)的區別Controller
- Android RxJava:這是一份RxJava使用入門學習指南AndroidRxJava
- SAP 沒有啟用HUM功能照常可以使用Handling Unit
- [譯] RxJava JDBC 簡介RxJavaJDBC
- Rxjava工作原理總結RxJava
- RxJava 系列-3:使用 SubjectRxJava
- RxJava/RxAndroid/AutoDispose/RxBinding/RxBusRxJavaAndroid