Предположим, нам надо выполнить параллельно несколько запросов на сервер с помощью, RxJava и Retrofit.
Скорее всего вы будете использовать такие объединяющие операторы: как combineLatest или zip. В итоге у вас получится
примерно такая цепочка:
val firstObservable = ServerApi().firstRequest( requestParams1 )
val secondObservable = ServerApi().secondRequest( requestParams2 )
val thirdObservable = ServerApi().thirdRequest( requestParams3 )
// объединяем Observable-ы в один с помощью combineLatest
Observable.combineLatest(
firstObservable,
secondObservable,
thirdObservable,
Function3<FirstResponse, SecondResponse, ThirdResponse, CombinedResult> { firstResponse, secondResponse, thirdResponse ->
// объединяем и создаем результат для Function3
CombinedResult( firstResponse, secondResponse, thirdResponse )
}
)
.flatMap { combinedResult ->
// здесь выполняем необходимые операции в случае необходимости
Observable.just(combinedResult) // return original observable unchanged
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ combinedResult ->
// end of request
// show result
}, {
it.printStackTrace()
})
В этой цепочке есть проблема. Если один из Observable-ов выбросит HttpException или любой другой Throwable, то вся цепочка прекратит выполнение в onError, и мы потеряем успешные данные от других запросов.
Как избежать этого? Все что нам нужно — это корректно обрабатывать ошибки от каждого из Observable-ов.
Для этого есть удобный оператор onErrorReturn() — он возвращает новый Observable в случае ошибки, без прекращения выполнения цепочки.
добавьте его вызов после каждого параметра (эммитера) в операторе combineLatest следующим образом:
Observable.combineLatest(
firstObservable
.onErrorReturn { responseFromException(it) },
secondObservable
.onErrorReturn { responseFromException(it) },
....

onErrorReturn — это удобный оператор, который эмитит новый объект вместо того, чтобы ломать цепочку в случае возникновения Exception-а
Для создания новых объектов, которые мы будем эмитить, напишите специальный метод или фабрику на дженериках, подходящую под ваши бизнес-требования:
...
// FirstResponse, SecondResponse and ThirdResponse should inherit from BaseResponse
fun <T : Any> responseFromException(throwable: Throwable): BaseResponse<T> {
var errorResponse: BaseResponse<T> = BaseResponse()
if (throwable is HttpException) {
errorResponse.code = it.code()
errorResponse.message = it.message()
}
return errorResponse
}
Вот и все. С помощью одной строчки для каждого из Observable-ов мы сделали нашу цепочку устойчивой к ошибкам.
Комментариев нет
You can leave the first : )