Administrando excepciones con flatMap
Como recomienda David Karnok en el artículo "flatMap part 1" y Dan Lew en el artículo "Error handling in Rxjava" para la administración de excepciones a través de flatMap se puede devolver el error directamente sin necesidad de envolverlo (wrapping). Esto aplica tanto para las excepciones tipo checked como las unchecked.
Observable.range(1, 10)
.flatMap(v -> {
if (v < 5) {
return Observable.just(v);
}
return Observable.error(new IOException("Why not?!"));
})
.subscribe(System.out::println, Throwable::printStackTrace);
Output:
1
2
3
4
java.io.IOException: Why not?!
Existe otra alternativa a través del uso de los argumentos del operador flatMap, sin embargo no es recomendable debido al costo de la operación, y además se debe tener cuidado en como se configura dentro del "chain de operadores".
Por ejemplo, en el siguiente código no se tiene efecto del manejo de la excepción:
Observable.just(10)
.flatMap(integer -> Observable.just(integer / 0), //Crash!
throwable -> Observable.error(new Exception("my custom error!")),
() -> Observable.just("complete"))
.doOnError(throwable -> System.err.println("doOnError"))
.subscribe(integer -> System.out.println(integer),
throwable -> System.err.println(throwable));
Output:
doOnError
java.lang.ArithmeticException: / by zero
Sin embargo, si el error se genera en el operador inmediatamente anterior al operador flatMap:
Observable.just(10)
.map(integer -> integer + 10/0) //Crash!
.flatMap(integer -> Observable.just(integer),
throwable -> Observable.error(new Exception("my custom error!")),
() -> Observable.just("complete"))
.doOnError(throwable -> System.err.println("doOnError"))
.subscribe(integer -> System.out.println(integer),
throwable -> System.err.println(throwable));
Output:
doOnError
java.lang.Exception: my custom error!
Adicionalmente, si se requiere dar un manejo particular a la respuesta ante una excepción se puede utilizar el operador onErrorReturn:
Observable.just(10)
.map(integer -> integer + 10/0) //Crash!
.flatMap(integer -> Observable.just(integer),
throwable -> Observable.error(new Exception("my custom error!")),
() -> Observable.just("complete"))
.doOnError(throwable -> System.err.println("doOnError"))
.onErrorReturn(error -> "Empty result")
.subscribe(integer -> System.out.println(integer),
throwable -> System.err.println(throwable));
Output:
doOnError
Empty result
ConversionConversion EmoticonEmoticon