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.
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();
}
}));
Vous pouvez également utiliser rx.observables.BlockingObservable, par exemple:
BlockingObservable.from(/**/).single();
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.
Vous pouvez utiliser Single.blockingGet pour un appel synchrone
// example
signIn(name,password).blockingGet()