web-dev-qa-db-fra.com

RxJava; Comment émettre des observables de manière synchrone

Je souhaite émettre de manière synchrone deux objets observables (qui sont asynchrones), l’un après l’autre, qui renvoie l’objet observable first emitted. Si le premier échoue, il ne devrait pas émettre le second.

Supposons que nous avons un observable qui connecte un utilisateur et un autre observable qui sélectionne automatiquement le compte de l'utilisateur, après la connexion. 

C'est ce que j'ai essayé:

public Observable<AccessToken> signInAndSelectAccount(String username, String password)
{

    Observable<AccessToken> ob1 = ...; // Sign in.
    Observable<Account> ob2 = ...; // Select account.


    return Observable.Zip(
            ob1,
            ob2,
            new Func2<AccessToken, Account, AccessToken>() {
                @Override
                public AccessToken call(AccessToken accessToken, Account account)
                {
                     return accessToken;
                }
            });
}

Cela ne fonctionne malheureusement pas pour mon cas d'utilisation. Il émettra/appellera les deux observables en parallèle, en commençant par 'ob1'.

Quelqu'un at-il rencontré un cas d'utilisation similaire? Ou avez-vous une idée sur la façon de faire en sorte que les observables s’attendent les uns les autres de manière synchrone, là où les premiers émis peuvent être renvoyés?

Merci d'avance.

7
Thomas Neuteboom

Il n’existe pas de terme «attente» dans la programmation réactive. Vous devez penser à la création d'un flux de données, où une Observable pourrait être déclenchée par un autre. Dans votre cas, après avoir reçu token, vous devez recevoir account. Cela pourrait ressembler à ceci:

Observable<Account> accountObservable = Observable.create(new Observable.OnSubscribe<AccessToken>() {
    @Override public void call(Subscriber<? super AccessToken> subscriber) {
        subscriber.onNext(new AccessToken());
        subscriber.onCompleted();
    }
}).flatMap(accessToken -> Observable.create(new Observable.OnSubscribe<Account>() {
    @Override public void call(Subscriber<? super Account> subscriber) {
        subscriber.onNext(new Account(accessToken));
        subscriber.onCompleted();
    }
}));
4
eleven

Vous pouvez également utiliser rx.observables.BlockingObservable, par exemple:

BlockingObservable.from(/**/).single();
6
netgui

Je ne connais pas Java, mais la solution à Scala serait probablement la suivante, j'espère qu'elle sera lisible par vous

import rx.lang.scala.Observable

class AccessToken
class Account

case class TokenAndAccount(token: AccessToken, account: Account)

val accessTokenSource = Observable.just(new AccessToken)
val accountSource = Observable.just(new Account)

accessTokenSource
   .flatMap(token ⇒ accountSource.map(account ⇒ TokenAndAccount(token, account)))
   .subscribe(tokenAndAccount ⇒ println(tokenAndAccount))

Fondamentalement, flatMap s'assurera que le accountSource.map... est utilisé uniquement après que le jeton de accessTokenSource a été émis. Dans le accountSource.map, nous combinons le jeton obtenu et le compte pour une utilisation ultérieure dans subscribe.

flatMap est l’un des opérateurs les plus utiles. Assurez-vous de lire sa documentation et peut-être quelques tutoriels.

1
Tomáš Dvořák

Vous pouvez utiliser Single.blockingGet pour un appel synchrone

// example 
signIn(name,password).blockingGet() 
1
Linh