2017-10-09 20 views
0

J'essaie de trouver un moyen d'exécuter des requêtes en parallèle et de les gérer lorsque toutes les observations sont terminées. Malgré tout fonctionne quand tous les observables donnent une réponse, je ne vois pas un moyen de gérer toutes les erreurs quand tout est fini.RxAndroid - Gérer les erreurs avec l'opérateur Zip

Ceci est un exemple de l'opérateur postal, qui exécute essentiellement 2 requêtes en parallèle:

Observable.zip(
       getObservable1() 
         .onErrorResumeNext { errorThrowable: Throwable -> 
          Observable.error(ErrorEntity(Type.ONE, errorThrowable)) 
         }.subscribeOn(Schedulers.io()), 
       getObservable2() 
         .onErrorResumeNext { errorThrowable: Throwable -> 
          Observable.error(ErrorEntity(Type.TWO, errorThrowable)) 
         }.subscribeOn(Schedulers.io()), 
       BiFunction { value1: String, value2: String -> 
        [email protected] value1 + value2 
       }) 
       //execute requests should be on io() thread 
       .subscribeOn(Schedulers.io()) 
       //there are other tasks inside subscriber that need io() thread 
       .observeOn(AndroidSchedulers.mainThread()) 
       .subscribe(
         { result -> 
          Snackbar.make(view, "Replace with your own action " + result, Snackbar.LENGTH_LONG) 
            .setAction("Action", null).show() 
         }, 
         { error -> 
          Log.d("TAG", "Error is : " + (error as ErrorEntity).error.message) 
         } 
       ) 


private fun getObservable1(): Observable<String> { 
    return Observable.defer { 
     throw Throwable("Error 1") 
    } 
} 

private fun getObservable2(): Observable<String> { 
    return Observable.defer { 
     throw Throwable("Error 2") 
    } 
} 

problème avec cette approche est qu'il n'y a pas de mécanisme pour se joindre à chaque erreur comme BiFunction faire pour le cas de succès. Par conséquent, l'opérateur zip déclenchera seulement la première erreur et ignorera les autres.

Sortie:

D/TAG: Error is : Error 1 

Est-il possible de récupérer toutes les erreurs que après chaque zip intérieur observable terminé ou a une erreur?

Mon but principal est de voir quelles requêtes ont donné une erreur et d'exécuter seulement celles-ci après qu'une boîte de dialogue apparaisse à l'utilisateur lui demandant s'il veut réessayer les demandes échouées.

+0

Il serait peut-être plus facile si vous n'avez pas continué avec l'erreur sur la prochaine reprise mais avec un objet wrapper qui contient l'erreur? – masp

+0

C'est une solution possible merci. Cependant, cela ne va pas à l'encontre du but d'avoir une méthode onError() onNext()? – iGoDa

+2

'but d'avoir une méthode onError() onNext()?' Cela dépend de ce que vous définissez comme "Erreur" dans votre système. Je suis d'accord avec l'article @LordRaydenMK mentionne et aussi [celui-ci] (http://blog.danlew.net/2015/12/08/error-handling-in-rxjava/). 'OnError' devrait être utilisé pour les cas où votre application/système ne sait pas comment gérer. Vous ne devriez pas lancer d'exceptions chaque fois que le système ne suit pas le "chemin heureux". – masp

Répondre

1

Vous pouvez modéliser vos observables à l'aide de classes de données. Par exemple.

sealed class Response { 
    data class Success(val data: String) : Response() 
    data class Error(val t: Throwable) : Response() 
} 

alors vous pouvez mapper vos observables à la réponse comme ceci:

val first: Observable<Response> = observable1 
     .map<Response> { Response.Success(it) } 
     .onErrorReturn { Response.Error(it) } 

val second: Observable<Response> = observable2 
     .map<Response> { Response.Success(it) } 
     .onErrorReturn { Response.Error(it) } 

et vous pouvez les combiner:

Observable.zip(
     first, 
     second, 
     BiFunction { t1: Response, t2: Response -> Pair(t1, t2) } 
).subscribe({println(it)}) 

cette impression:

(erreur (t = java.lang.Exception: Erreur 1), Erreur (t = java.lang.Exception: Erreur 2))

Jetez aussi un coup d'œil à this article.