Sponsored By Aspose - File Format APIs for .NET

Aspose are the market leader of .NET APIs for file business formats – natively work with DOCX, XLSX, PPT, PDF, MSG, MPP, images formats and many more!

Introduction to the Reactive Extensions for JavaScript – Looping Operators

After spending the past couple of posts talking about how we integrate and why, let’s get back to the basic operators of the Reactive Extensions for JavaScript.  After covering the conditional operators of If and Case, let’s go deep into looping constructs.  The Reactive Extensions gives us two options for dealing with looping constructs, a For and a While loop which do pretty much what you think they do.  Let’s get started by covering the For loop.

Also, before we get started on the usual links, do check out Jeffrey Van Gogh’s performance (with me in the background) at JSConf on the B Track talking about the Reactive Extensions for JavaScript.

Before we get started, let’s get caught up to where we are today:

Looping with Observable.For

The first looping construct we’re going to look at is the For loop.  What this does is that it takes an array, runs through the result selector on that value and then concatenates the observable sequences obtained.  You can think of this as a standard for loop, but it concatenates the results together into a single observable sequence.  Below is the signature for this method:

// source : Array<Source>
// selector : Source -> Observable<Result>

// returns : Observable<Result>

Rx.Observable.For(
    source,
    selector);

We can show how this works through a quick example of the For in action by starting out with a simple array and then appending a value to the front of it.  Note that the selector function takes in the current value and must return an observable value, hence my use of the Rx.Observable.Return function.

var obj = [1,2,3];

Rx.Observable.For(
    obj,
    function(item) {
        return Rx.Observable.Return("foo" + item);
    })
    .Subscribe(
        function(result) {
            $("<p/>").html(result).appendTo("#content");
        });

In this case, we’ll get the following result on our screen:

foo1
foo2
foo3

You may notice here that the overall semantics of this method is similar to calling FromArray and then SelectMany on a given array.  Now that we have an idea of how we can use this, let’s see this in a more detailed fashion.  What we’re going to do is query Twitter for the usual term, then iterate through each result, and if there is a geo record, then we’ll call the Bing Geolocation REST service to get the best guess at the actual address.  As you can see below, we’re going to reuse a little bit of our knowledge from the previous post to use the Rx.Observable.If where we check whether we have a geo record and if we do, then we query the service, else we return an empty observable.  And once again with our If function, we need to ensure since JavaScript is an eager language that we defer the hot observable that is an AJAX call until the condition calls for it.

searchTwitter("4sq.com").SelectMany(
    function(data) {
    
        return Rx.Observable.For(
            data.results,
            function(result) {
            
                return Rx.Observable.If(
                    function() { return result.geo != null; },
                    Rx.Observable.Defer(
                        function() { 
                            var lat = result.geo.coordinates[0];
                            var lon = result.geo.coordinates[1];
                            return geolocate(lat, lon);
                        }),                    
                    Rx.Observable.Empty(Rx.Scheduler.Timeout));
            });
    })
    .Subscribe(
        function(location) {
            var address = location.resourceSets[0].resources[0].name;
            $("<p/>").html(address).appendTo("#content");
        });

And just for full disclosure, here are the searchTwitter and geolocate functions defined:

function searchTwitter(term) {
    return $.ajaxAsObservable(
        { url : "http://search.twitter.com/search.json",
          dataType : "jsonp",
          data : { q : term, rpp : 100 } })
        .Select(function(d) { return d.data; });
}

function geolocate(lat, lon) {
    var key = "get your own key";
    var latlng = lat+","+lon;

    return $.ajaxAsObservable(
        { url : "http://dev.virtualearth.net/REST/v1/Locations/"+latlng,
          dataType : "jsonp",
          jsonp : "jsonp",
          data : { key : key, o : "json" } })
        .Select(function(d) { return d.data; });
}

Now that we’ve thoroughly looked at For loops, let’s move on to the While loop.

Looping with Observable.While

The next looping statement we’re going to talk about is the While loop.  This allows us to repeat our given source until the condition no longer holds (returns false).  Let’s take a look at the method signature for this:

// condition : () -> bool
// source : Observable<Source>

// returns : Observable<Source>

Rx.Observable.While(
    condition,
    source);

Let’s walk through a simple example of using this where we repeat a given source until our condition no longer holds.  In this instance we’ll check if our x variable is less than 10, and if so, keep repeating our observable sequence of 1.  The result will be writing 5 1s on the screen in addition to the x value.

var x = 0;

Rx.Observable.While(
    function() { return x < 5; },
    Rx.Observable.Return(1))
    .Subscribe(
        function(value) {
            x++;
            $("<p/>").html(value+"-"+x).appendTo("#content");
        });

And our result should look like the following:

1-1
1-2
1-3
1-4
1-5

And there you have it, two ways of dealing with looping, either with For loops or with While loops.  But, before we wrap this up, I’ll get back to those .NET folks.

Back to .NET

Once again, I didn’t forget about the .NET world in this post.  We can use pretty much the same syntax as we did for our JavaScript version in .NET.  Let’s look first at the For method signature, which should look identical to the JavaScript version if you squint enough.  This takes in an IEnumerable<T> as the source and then a Func<T, IObservable<TResult>> as the result selector and returns to use an IObservable<TResult>

public static IObservable<TResult> For<TSource, TResult>(
    IEnumerable<TSource> source,
    Func<TSource, IObservable<TResult>> resultSelector
)

And once again like above, we can do some simple iteration over a simple range, and then square each value as it comes through.

IEnumerable<int> range = Enumerable.Range(1, 10);

Observable.For(
    range, 
    x => Observable.Return(x * x))
    .Subscribe(x => Console.WriteLine(x));

This yields to us the following result:

1
4
9
16
25
36
49
64
81
100

Like the For method above, the While method follows exactly its JavaScript counterpart in terms of syntax once you squint again.  This method takes a Func<bool> condition delegate and a source to repeat while the condition holds.  This returns to us an IObservable<TSource> back to us as the result.

public static IObservable<TSource> While<TSource>(
    Func<bool> condition,
    IObservable<TSource> source
)

And we can run through the same While example as above transcribed from JavaScript to C#.

int timesCalled = 0;

Observable.While(
    () => timesCalled < 5,
    Observable.Return(1))
    .Subscribe(x =>
    {
        timesCalled++;
        Console.WriteLine(x + "-" + timesCalled);
    });

With these two posts I’ve covered some really interesting imperative constructs that can integrate nicely with the Reactive Extensions.  Covering these is leading me towards my next post, which is to cover why these were added in the first place…

Conclusion

Dealing with asynchronous programming has been in the forefront of many minds in the JavaScript community.  At JSConf, there were several examples of frameworks trying to get around the idea of callbacks and instead lean more towards composition.  By utilizing the Reactive Extensions for JavaScript, we’re able to compose together asynchronous and event-based operations together and transform the results in interesting ways.

When we start creating more advanced workflows through the Reactive Extensions, we need powerful ways of expressing such concepts as looping logic outside of the Skip/While, Take/While and so forth.  With the addition of the For and While operators, we have even more ways to describe our workflows.

So with that, download it, and give the team feedback!

This entry was posted in Event-based Porgramming, JavaScript, JSConf, Reactive Framework. Bookmark the permalink. Follow any comments here with the RSS feed for this post.