Rx中, 很容易處理異常, 整個鏈?zhǔn)秸{(diào)用過程中,如果異常不做處理, 最后都會交給onError
;
不要過渡的依賴onError
; onError
應(yīng)該是在數(shù)據(jù)實在是無法處理的情況下,才被調(diào)用; 因為onError
一旦被調(diào)用, 即意味著整個事件流結(jié)束;
在傳統(tǒng)的Java中, 一般產(chǎn)生異常, 可以自己決定處理或者拋出, 在Rx中也類似, 可以自己決定在產(chǎn)生異常后, 如何處理;
Catch
和傳統(tǒng)Java中Catch類似, 獲取異常,然后自行決定如何處理;
onErrorReturn
onErrorReturn
操作符作用: 當(dāng)發(fā)生錯誤是, 發(fā)送一個默認(rèn)值,然后結(jié)束數(shù)據(jù)流(即調(diào)用onComplete
); 使用后,Subscribe的onError
方法不會被調(diào)用,會正常的調(diào)用onComplete
結(jié)束;
onErrorResumeNext
onErrorResumeNext
操作符的作用: 當(dāng)錯誤發(fā)生時, 用一個數(shù)據(jù)流代替當(dāng)前數(shù)據(jù)流, 繼續(xù)發(fā)送數(shù)據(jù); 和上面一樣,Subscribe的onError方法不會被調(diào)用
onExceptionResumeNext
onExceptionResumeNext
類似, 唯一的區(qū)別就是onExceptionResumeNext
捕獲的是異常
如果拋出的Throwable不是一個Exception, 該操作符無法捕獲
Retry
如果發(fā)生了異常, 也可以使用retry
重新訂閱; 使用retry
重新訂閱數(shù)據(jù)流后, Observable會從頭重新發(fā)射數(shù)據(jù), 意味著可能會重復(fù)處理數(shù)據(jù)
retry有三個重載方法
- retry 無限重新訂閱
- retry(long) 帶有最大重試次數(shù), 次數(shù)超過,則不再重試
- retry(Func) 帶有一個判讀函數(shù), 如果返回true, 則重試; 返回false,則結(jié)束
retryWhen
retryWhen
和retry
類似, 不過接受一個函數(shù), 該函數(shù)返回一個Observable, 由Observable發(fā)射的數(shù)據(jù), 決定是否需要重新訂閱
- 如果返回的Observable發(fā)射一個數(shù)據(jù), 則重新訂閱
- 如果返回的Observable發(fā)射一個錯誤, 則不會重試
返回的Observable發(fā)射的數(shù)據(jù)類型不重要; Observable只是用來判斷是否需要重試
不結(jié)束當(dāng)前數(shù)據(jù)流, 捕獲(處理,忽略)異常
在平常編碼中, 處理一序列的數(shù)據(jù), 通常對其中的一個數(shù)據(jù)處理異常時, 我們通常會捕獲忽略異常, 跳過該數(shù)據(jù), 繼續(xù)處理剩下的數(shù)據(jù);
上述的操作符中, 上面的操作符并不能實現(xiàn)該功能; onErrorReturn
遇到異常時,會結(jié)束該數(shù)據(jù)留, 不會處理剩下的數(shù)據(jù); 而retry
會從頭重新發(fā)射數(shù)據(jù), 有重復(fù)數(shù)據(jù);
這種情況需要和flatMap
一起搭配使用; flatMap
可以把每項數(shù)據(jù)轉(zhuǎn)換成為一個Observable, 然后就可以針對每個數(shù)據(jù)處理異常了
Random random = new Random();
Observable<Integer> observable =
Observable.create(o -> {
o.onNext(random.nextInt());
o.onNext(random.nextInt());
o.onError(new Exception());
o.onNext(random.nextInt());
}).flatMap(o -> Observable.just(o)
.map(Object::toString)
.map(Integer::valueOf)
.onErrorReturn(throwable -> -1)
);