简体   繁体   中英

RxJava; How to emit observables synchronously

I want to synchronously emit two Observable objects (which are asynchronous), one after the other where it returns the first emitted Observable object. If the first one fails, it should not emit the second one.

Let's say we have one Observable that signs a user in, and another Observable that automatically selects the user's account, after signing in.

This is what I tried:

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;
                }
            });
}

This unfortunately does not work for my use case. It will emit/call both observables parallel, starting with 'ob1'.

Did someone encounter a similar use case? Or has an idea on how to make observables wait for eachother in a synchronous way, where the first emitted can be returned?

Thanks in advance.

您还可以使用 rx.observables.BlockingObservable 例如:

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

You can use Single.blockingGet for synchronous call

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

There is no such term as "wait" in reactive programming. You need to think about creating of a data stream, where one Observable could be triggered by another. In your case after receiving token you need to receive account . It could look like this:

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();
    }
}));

I don't know Java, but the solution in Scala would probably be this, hope it is readable to you

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))

Basically flatMap will make sure that the accountSource.map... is used only after the token from accessTokenSource has been emitted. Inside the accountSource.map we combine the obtained token and account together for later usage in subscribe .

flatMap is one of the most useful operators, be sure to read it's docs and perhaps some tutorials.

Also, we can use .toBlocking() method in Observable which will make as BlockingObservable . ie,

Observable.just().toBlocking();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM