3

In jQuery, the idea of promises is done via:

var taskA = $.Deferred();
var taskB = $.Deferred();
var taskC = $.Deferred();

// Callback starts when all tasks are complete/resolved
$.when(taskA, taskB, taskC).done(function(results) {
    var resultA = results[0];
    var resultB = results[1];
    var resultC = results[2];
    // ...
});

// Fire off long tasks
longTask1(function(result) { taskA.resolve("result"); });
longTask2(function(result) { taskB.resolve("result"); });
longTask3(function(result) { taskC.resolve("result"); });

I feel like there should be an equivelant in RxJava but I don't know the name of it.

edit: Adding my Android activity code for clarification

/**
 * What I expected to happen:
 * - User has to click buttons A, B and C in order to pass.
 *
 * What actually happens
 * - User clicks any button and passes.
 */
public class RxTestActivity extends AppCompatActivity {
    PublishSubject<Boolean> subjectClickedA;
    PublishSubject<Boolean> subjectClickedB;
    PublishSubject<Boolean> subjectClickedC;

    @Bind(R.id.btnA) Button btnA;
    @Bind(R.id.btnB) Button btnB;
    @Bind(R.id.btnC) Button btnC;
    @Bind(R.id.labelTest) TextView txtSuccess;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_test);
        ButterKnife.bind(this);

        subjectClickedA = PublishSubject.create();
        subjectClickedB = PublishSubject.create();
        subjectClickedC = PublishSubject.create();

        // Create an observer which waits until all 3 tasks are complete before
        // triggering it's own "onCompleted".
        Observable.merge(subjectClickedA, subjectClickedB, subjectClickedC)
            // Ensure all subjects are completed
            // TODO: doesn't work
            .all(new Func1<Boolean, Boolean>() {
                @Override
                public Boolean call(Boolean aBoolean) {
                    // Won't let anything through until all of tasks are complete
                    return subjectClickedA.hasCompleted() && subjectClickedB.hasCompleted() && subjectClickedC.hasCompleted();
                }
            })
            .subscribe(new Subscriber<Boolean>() {
                @Override
                public void onError(Throwable e) {
                }

                @Override
                public void onNext(Boolean aBoolean) {
                    // aBoolean value comes in as false
                    Log.e("Subscriber onNext", String.valueOf(aBoolean));
                }

                @Override
                public void onCompleted() {
                    // This triggers on the first button click (no matter which one)
                    // TODO: reward user
                    Log.e("Subscriber", "all tasks completed!");
                    txtSuccess.setText("Great success!");
                }
            });
    }

    @OnClick(R.id.btnA)
    protected void onButtonAClicked() {
        subjectClickedA.onNext(true);
//        subjectClickedA.onCompleted();

        btnA.setEnabled(false);
    }

    @OnClick(R.id.btnB)
    protected void onButtonBClicked() {
        subjectClickedB.onNext(true);
//        subjectClickedB.onCompleted();

        btnB.setEnabled(false);
    }

    @OnClick(R.id.btnC)
    protected void onButtonCClicked() {
        subjectClickedC.onNext(true);
//        subjectClickedC.onCompleted();

        btnC.setEnabled(false);
    }
}
twig
  • 4,034
  • 5
  • 37
  • 47

1 Answers1

2

You can combine the multiple Observable by multiple ways.

Please take a look into this.Combining Observables

This section explains operators you can use to combine multiple Observables.

  • startWith( ) — emit a specified sequence of items before beginning to emit the items from the Observable
  • merge( ) — combine multiple Observables into one
  • mergeDelayError( ) — combine multiple Observables into one, allowing error-free Observables to continue before propagating errors
  • zip( ) — combine sets of items emitted by two or more Observables together via a specified function and emit items based on the results of this function (rxjava-joins) and( ), then( ), and when( ) — combine sets of items emitted by two or more Observables by means of Pattern and Plan intermediaries
  • combineLatest( ) — when an item is emitted by either of two Observables, combine the latest item emitted by each Observable via a specified function and emit items based on the results of this function
  • join( ) and groupJoin( ) — combine the items emitted by two Observables whenever one item from one Observable falls within a window of duration specified by an item emitted by the other Observable
  • switchOnNext( ) — convert an Observable that emits Observables into a single Observable that emits the items emitted by the most-recently emitted of those Observables
Amit Gupta
  • 8,914
  • 1
  • 25
  • 33
  • Hmm, I might be missing something but how does an Observable/Subject mark itself as complete? I'm using PublishSubject.onNext(true) and onComplete() but it doesn't seem to get past zip() – twig Apr 04 '16 at 00:45