From jQuery Deferred to RxJS ForkJoin

In a recent posting I blogged about how to process some code after several asynchronous operations have finished and how to access each return value of those operations no matter in which order those would finish.

To make this happen I used the new jQuery Deferred API. While this is a great way, I would also like to show you that there are other (even more advanced) ways to do so.

One of my heart warming interests is to dig deep into reactive functional programming and therefore digging into RxJS.

So let’s see how we can rewrite our example to make use of RxJS!

$(document).ready(function(){

    var example = function (){
        var deferred = new Rx.AsyncSubject();

        setTimeout(function(){
            deferred.OnNext(5);
            deferred.OnCompleted();
        }, 1000); //Will finish first

        return deferred;
    };

    var example2 = function (){
        var deferred = new Rx.AsyncSubject();
        setTimeout(function(){
            deferred.OnNext(10);
            deferred.OnCompleted();

        }, 2000); //Will finish second

        return deferred;
    };

    Rx.Observable
      .ForkJoin(Example(), Example2())
      .Subscribe(function(args){
            console.log("Example1 (Should be 5): " + args[0]);
            console.log("Example2 (Should be 10): " + args[1]);
          });
    });

As you can see, nothing ground shaking happened to our code. Things are just named slightly different.

Did we gain anything? Yes, we did! ForkJoin not only combines two observable streames and waits until both have finished, but in fact returns a new observable stream. Having an observable stream as an first class object is a major benefit! For example, let’s say we are only interested if first stream matches a certain condition. We can just filter out the undesired values using the Where operator.

    Rx.Observable
      .ForkJoin(Example(), Example2())
      .Where(function(x){ return x[0] == 5; })
      .Subscribe(function(args){
            console.log("Example1 (Should be 5): " + args[0]);
            console.log("Example2 (Should be 10): " + args[1]);
          });
    });

And once again, the Where operator returns a new observable stream. This is great in terms of composability. You can easily just hand this new observable stream over to another component which will react on a stream of data that exactly matches the conditions the component was intended for.

Having events as first class citizen which you can compose and pass on, is what makes Rx so great.

Advertisements