Comment remplacer les 'if' avec rx-java pour éviter le rappel de l'enfer?
Je cherche à remplacer mon code avec rx-java. (Il est très petit code.)
C'est fini et ça fonctionne.
Mais je veux savoir...
- Est-ce une bonne Rx style?
- Si pas bon, veuillez indiquer mauvais point
Ci-dessous mon code qui est de l'api de manipulation.
avant
Random r = new Random();
boolean apiResult = r.nextBoolean(); //it represents api result. ex. {"result": true} or {"result": false}
if (apiResult == true) {
//do something
System.out.println("result:" + "success");
} else {
//do something
System.out.println("result:" + "failure");
}
après
Random r = new Random();
Observable<Boolean> apiResultStream = Observable.create(new OnSubscribe<Boolean>() {
@Override
public void call(Subscriber<? super Boolean> subscriber) {
//emit true or false
subscriber.onNext(r.nextBoolean());
}
}).cache(1);
//I used filter for split. Is it Rx style?
//success if true emitted.
Observable<Boolean> successStream = apiResultStream
.filter(aBoolean -> aBoolean == true); //here
//failure if false emitted.
Observable<Boolean> failureStream = apiResultStream
.filter(aBoolean -> aBoolean == false); //here
//success flow
successStream
.flatMap(aBoolean -> Observable.just("success"))
//and do something
.subscribe(aString -> System.out.println("result:" + aString));
//failure flow
failureStream
.flatMap(aBoolean -> Observable.just("failure"))
//and do something.
//I want to keep subscriber.
.subscribe(aString -> System.out.println("result:" + aString));
MODIFIER
J'ai presque remplacé. merci pour les bon commentaire.
(mais j'ai un peu de non-remplacement de code. Il ont beaucoup de rappel et si le relevé).
Je veux éviter de "rappel de l'enfer'.
La clé est différente type de résultat entre les "callSuccessApi" et "callFailureApi'
avant rx
//callback hell!
callApi(new Callback<Result>(){
@Override
public void success(Result result) {
if (result.Response == true) {
callSuccessApi(new Callback<ResultSuccess>(){
@Override
public void success(ResultSuccess result) {
//and more callbacks...
}
}
} else { //result.Response == false
callFailureApi(new Callback<ResultFailure>(){
@Override
public void success(ResultFailure result) {
//and more callbacks...
}
}
}
}
}
après avec rx(éviter de rappel de l'enfer! Est-ce une bonne Rx style?)
//change 1st api to observable.(I changed other api to observable)
Observable<Result> apiResultStream = Observable.create(new OnSubscribe<Boolean>() {
@Override
public void call(Subscriber<? super Boolean> subscriber) {
callApi(new Callback<Result>(){
@Override
public void success(Result result) {
subscriber.onNext(result);
}
});
}
}).cache(1); //ensure same Observable<Result> for success and failure.
//I used filter for split. Is it Rx style?
//success if result.response == true.
Observable<ResultSuccess> successStream = apiResultStream
.filter(result -> result.response == true); //here
//failure if result.response == false.
Observable<ResultFailure> failureStream = apiResultStream
.filter(result -> result.response == false); //here
//success flow. callSuccessApi return Observable<ResultSuccess>
successStream
.flatMap(result -> callSuccessApi(result))
//and more api call with flatMap...
.subscribe(resultSuccessN -> System.out.println("result:" + resultSuccessN.toString()));
//failure flow. callFailureApi return Observable<ResultFailure>
failureStream
.flatMap(resultFailure -> callFailureApi(result))
//and more api call with flatMap...
.subscribe(resultFailureN -> System.out.println("result:" + resultFailureN.toString()));
désolé pour mon mauvais anglais et longue question.
Mis À Jour Mon Code
J'ai eu 2 informations importantes dans cette question.(merci @Tomáš Dvořák, @Will
- si c'est une bonne voie à suivre dépend de la situation particulière.
- Il n'y a rien de mal à utiliser une instruction if dans une carte /flatmap /abonnez-vous.
mise à jour du code
Observable<Result> apiResultStream = Observable.create(new OnSubscribe<Boolean>() {
@Override
public void call(Subscriber<? super Boolean> subscriber) {
callApi(new Callback<Result>() {
@Override
public void success(Result result) {
subscriber.onNext(result);
}
});
}
});
//In this case, I used 'if' for simply and cleanly.
apiResultStream
.subscribe(result -> {
if (result.response == true) {
callSuccessApi(); //this line looks like 'callback'. but I used this for simply and cleanly.
} else {
callFailureApi();
}
});
apiResultStream.subscribe(aBoolean -> if (aBoolean) {doSomething} else {doSomethingElse}
. Avec cette approche, vous n'avez même pas besoin de le mettre en cache (ce qui était bizarre de toute façon). Il est difficile de recommander plus quand on ne sais pas ce que vous voulez atteindre.merci des bons conseils. J'ai mis à jour question afin d'éviter de rappel de l'enfer'.
Même après votre mise à jour, le problème que vous avez présenté, c'est que vous souhaitez effectuer l'une des deux côté-effectuer des actions en fonction de la valeur du booléen observables. Ma solution simple s'applique toujours et résout votre exemple, simplement et proprement. En fait, si vous avez un autre problème à résoudre, s'il vous plaît poster. Btw, bien sûr, vous pouvez utiliser
filter
de diviser le flux, mais, encore une fois, si c'est une bonne voie à suivre dépend de la situation particulière.J'ai compris pourquoi votre solution est la bonne. J'ai appliqué à mon code. Le code est devenu simple et propre. situation, c'est important! je vous remercie.
OriginalL'auteur kyanro | 2015-02-03
Vous devez vous connecter pour publier un commentaire.
Il y a des tas de façons de le faire et cela dépend vraiment de votre cas d'utilisation. En général, je ne veux pas me couper en 2 dans le flux, ce qui rend votre code moins lisible. Aussi, je ne sais pas quels sont les avantages que vous obtenez de la flatMap appel. Il n'y a rien de mal à le faire si des choses à l'intérieur d'une carte d'appel.
Voici quelques options:
1 - Pour l'ajout de la journalisation (un peu comme votre lignes d'impression), j'utilise
doOnEach()
2 - Le travail que vous faites est une partie de votre flux, et vous allez avoir à faire plus de travail sur le stream plus tard - l'utilisation
map
3 - Si c'est un travail que vous voulez faire à la fin de la canalisation, c'est à dire après tous de transformation ou d'autres flux de travail est terminée, puis faire dans le abonnez-vous appeler.
Le problème est - avec un cas simple d'utilisation, il est difficile pour vous proposer la meilleure option, mais j'apprécie que dans l'apprentissage Rx, comment faire des instructions conditionnelles peut sembler déroutant. En général, je viens d'utiliser
map
ouflatMap
quand je suis à l'appel d'une autre méthode qui renvoie unObservable
et faire ma logique là-dedans.Mise à jour
Toujours pas sûr de savoir pourquoi vous êtes la division de votre flux. Sauf si vous commencez à être à l'aise avec les différents threads, la première abonnez-vous appel à bloquer le second qui n'est probablement pas ce que vous voulez. Aussi, si vous n'appelez pas inscrire plus d'une fois, alors vous n'avez pas besoin de la
cache()
appel.Il n'y a rien de mal avec l'aide d'un
if statement
au sein d'unemap
/flatmap
/subscribe
. Surtout si cela rend votre code plus lisible.Je ferais le suivant:
Bien plus propre.
Je suis un peu confus par votre
System.out.println
appels en abonnez-vous. Est-ce là pour le débogage ou de l'exploitation forestière? Si si, il suffit de le faire au sein de la ci-dessus flatMap dans l'instruction if.Espère que cette aide,
Sera
Mise à jour de réponse afin de refléter la mise à jour.
désolé pour la confusion. println représentés 'doSomething'. Mon code à un autre type de retour entre callSuccessApi et callFailureApi. Dans ce cas, puis-je appliquer cette solution?
Oui, vous pouvez avoir différents types de retour. Si vous êtes à l'aide de Java8 lambdas puis le type de retour est déduit, sinon, vous aurez besoin d'utiliser
Observable<?>
. Si lecallSuccesAPI
appel est prévu que la résiliation de l'opération - c'est à dire que c'est la fin de l'écoulement de l'eau, alors il est parfaitement logique de le faire dans le abonnez-vous appel.J'ai compris. si je n'ai pas besoin de "type de retour "dans " onNext", il est parfait! (C'est à dire, 'fin notifycation'). (ou, dans certains cas, je peux utiliser "instanceof" dans "onNext" pour "type de retour'). un bon moyen de faire dépend de la situation particulière!.
OriginalL'auteur
Pour éviter le si/d'autre et de ne pas briser la chaîne™, j'aime utiliser, de publier et de fusion et de scission et de re-fusionner le stream:
OriginalL'auteur