Clean up your code with RxJS!

Today I would like to talk a bit about the Reactive Extensions for JavaScript (aka LinqToEvents).  From when I heard the first rumors about it, I had a very keen eye on the project because I just felt there was something fascinating about it.

Unfortunatly, I didn’t really “got it right” and never found a real use case to test things out. But with all this noise around the new jQuery deferred API I recognized some common ground between those two technics and started digging into RxJS/Rx .NET again.

Finally, I was able to scratch a bit on the surface which I would like to share with you 🙂

So let’s say you have built a web app with a search textbox that fires up an ajax request while the user is typing. This is quite common and I’m sure you have done that before.

You don’t want to fire up the ajax call on every keystroke but only when the user stopped typing instead.  So, you just encountered the first brainer. What does it mean “when the user stopped typing”?

There is no native way to do something like that:

$(“#searchinput”).bind(“StoppedTyping”, function() {console.log(“stopped typing”)};

What you actually mean is, “I want this code only to execute when 500 milliseconds have passed after the last occurrence of the ‘keyup’ event”.

So, maybe u managed this by saving a timestamp inside an outter var. Or you were lucky enough to come up with a solution which doesn’t  rely on an outter var at all.

This is the Rx way to acomplish what I described earlier. How does that look for you? Pretty straight forward, isn’t it?

$(document).ready(function(){
    $('#myInput')
        .toObservable("keyup")
        .Select(function(){ return $('#myInput').val(); })
        .Throttle(500)
        .Subscribe(function(text){ console.log("fire up ajax call"); });
});

There is no outter var, therefore no side effect. I’m not going much into the details because there are better resources to look this up.

So let’s sum things up so far. While you type, nothing fires. The call will fire after you finished typing. But what if you finished typing a word, the call fires, you type again but end up with the same word for which you just fired the ajax call, the moment before. Let’s say we want avoid such a needless call. It’s trivial with RxJS!

$(document).ready(function(){
    $('#myInput')
        .toObservable("keyup")
        .Select(function(){ return $('#myInput').val(); })
        .Throttle(500)
        .DistinctUntilChanged()
        .Subscribe(function(text){ console.log("fire up ajax call"); });
});

Easy, isn’t it?

Or how about avoiding calls, for words with less than three letters?

$(document).ready(function(){
    $('#myInput')
        .toObservable("keyup")
        .Select(function(){ return $('#myInput').val(); })
        .SkipWhile(function(text){ return text.length < 3; })
        .Throttle(500)
        .DistinctUntilChanged()
        .Subscribe(function(text){ console.log("fire up ajax call"); });
});

This is just scratching the surface of what can be down with RxJS. I’m just starting my RxJS journey…but I like what I have seen so far!

Advertisements

Accessing return values from multiple Deferreds

It’s been a while since I wrote my last posting. As I feel that I am constantly in a hurry I rarely manage to find some time *sigh*.

However, too many interesting stuff which is worth blogging keeps flooding our beloved tech world! One of those things is the new Deferred object in jQuery 1.5.

I won’t go into every detail about what Deferreds are for because Eric Hynds already wrote an awesome article about it.

Just to give an example: Some month ago, I asked on stackoverflow which was the best way to spin off several async calls and do something when all those async calls have completed. Well, that’s one of the things that Deferreds can solve.

Today I want to show you how to deal with that and also how to deal with it if each call returns a value which you need to have access to afterwards.

Let’s look at this code:

$(document).ready(function(){

    var example = function (){
        var deferred = $.Deferred();

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

        return deferred.promise();
    };

    var example2 = function (){
        var deferred = $.Deferred();
        setTimeout(function(){
            deferred.resolve(10);
        }, 2000); //Will finish second

        return deferred.promise();
    };

    $.when(example(), example2())
        .then(function(arg1, arg2){
            console.log("Example1 (Should be 5): " + arg1);
            console.log("Example2 (Should be 10): " + arg2);
          });
    });

jsFiddle: http://jsfiddle.net/cburgdorf/M4JKR/

We created two Deferred objects (Example1, Example2) which both resolve with an return value. In the callback, which is called on $.then we have access to those return values. It might be obvious to you (but wasn’t to me) that those parameters will be sorted in the order in which the Deferreds were registered to $.when. That means, no matter in which order those async operations complete, you will be save to access the values in the expected order.

Here comes the proof with the operations turned around:

$(document).ready(function(){

    var example = function (){
        var deferred = $.Deferred();

        setTimeout(function(){
            deferred.resolve(5);
        }, 2000); //Will finish second

        return deferred.promise();
    };

    var example2 = function (){
        var deferred = $.Deferred();
        setTimeout(function(){
            deferred.resolve(10);
        }, 1000); //Will finish first

        return deferred.promise();
    };

    $.when(example(), example2())
        .then(function(arg1, arg2){
            console.log("Example1 (Should be 5): " + arg1);
            console.log("Example2 (Should be 10): " + arg2);
          });
    });

jsFiddle: http://jsfiddle.net/cburgdorf/vmLfF/

There is a lot more to discover with jQuery Deferreds, but I hope you found this little piece useful 😉