Introduction to the Reactive Extensions for JavaScript – Wikipedia Lookup

We’ve covered a bit of ground already in this series on the Reactive Extensions for JavaScript (RxJS) from the basic information, creating observers and observables, jQuery integration, composing asynchronous methods with callbacks and in the last post, talking about turning blocking calls into asynchronous calls.  Now that we have some more fundamental building blocks, let’s see what else we can do with it.  Before I move into FlapJax examples translated to the Reactive Extensions for JavaScript, I want to first visit a basic autocomplete/lookup scenario in which we can query a data source as we type, as such sites as Bing, Google, Wikipedia and others do.  In this example, we’ll use Wikipedia as the backend source for doing our autocomplete.

Also, if you’re at Mix this year, you’ll notice that Erik Meijer is giving a talk on the Reactive Extensions for JavaScript. I highly recommend that you go to this session, especially if you’ve been interested in this series.  Prepare for some pretty slick demos to show off the functionality of the library. 

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

Building a Lookup with Wikipedia

Our overall goal is to show how an autocomplete/lookup scenario might work using the Reactive Extensions for JavaScript.  I’ll show the basic mechanisms of querying the data set and returning the data, but the actual integration into a div could be up to you.  For simplicity sake, I’ll just stick the results into an unordered list for display purposes.  First, we need to familiarize ourselves with the Wikipedia API.  In order for us to do a basic open search, we can use the following URL where the <term> is replaced with your query.

http://en.wikipedia.org/w/api.php?action=opensearch&search=<term>&format=json

For example, I can search for Matthew using the Wikipedia API, and in JSON format, it should look like the following, where it returns a string array with the first element being my query, and the second element being an array of my search results.

["Matthew",["Matthew the Evangelist",
            "Matthew C. Perry",
            "Matthew Broderick",
            "Matthew Flinders",
            "Matthew McConaughey",
            "Matthew Arnold",
            "Matthew Perry",
            "Matthew Hayden",
            "Matthew Sweet",
            "Matthew Fox (actor)"]]

Knowing this, we could create an AJAX call to the API based upon a term and then only select the second element, our results, as our observable sequence.  In order to enable AJAX functionality, the Reactive Extensions for JavaScript comes with the XmlHttpRequest method which has two overloads, one that takes a simple string URL and that takes an XmlHttpRequestDetails which contains details about the request.  Let’s look at the signatures of the XmlHttpRequest methods:

function XmlHttpRequest(
    details); // An XmlHttpRequest details instance
    
function XmlHttpRequest(
    url);    // The URL of the request

And to give you an idea XmlHttpRequestDetails looks like, let’s look at the properties exposed on this class which include the headers, method, user, password and URL.

function XmlHttpRequestDetails() {
    this.Headers  // Adds custom HTTP headers to the request
    this.Method   // Specifies method GET, POST, HEAD
    this.Password // Password for authentication
    this.Url      // Url for request
    this.User     // User for request
};

Now, let’s function called searchWikipedia that takes our search term and creates an XmlHttpRequest to Wikipedia and then projects the proper results.  To do this, we’ll call the Rx.Observable.XmlHttpRequest method and then call Select to turn the eval the JSON response and select the second item in the array, our array of results.

function searchWikipedia(term) {
    var url = "http://en.wikipedia.org/w/api.php"+
        "?action=opensearch&search="+term+"&format=json";
    
    return Rx.Observable.XmlHttpRequest(url)
        .Select(function(result) {
            var response = eval(result.responseText);
            if(response.length == 2) return response[1];
            else return [];
        });
}

Now, let’s hook it all together, so that when a key goes up, that is to say enters a value, then we’ll trigger a search to Wikipedia.  Our simple search screen looks nothing more than a simple input for our text value and a UL for our results, and an area for errors should one occur.

<body>
    <input id="searchInput" size="100" type="text" />
    <ul id="results" />
    <p id="error" />
</body>

Once the document loads, we want the ability to track the keyup event of our searchInput and then display the results (if any) in our results, else populate the error.  As per usual, we’ll wrap this functionality into our document.ready function.

$(document).ready(function() {
    // Code goes here
});

The next part is the fun part.  We need to take our searchInput and listen to the keyup event. 

var searcher = $("#searchInput")
    .ToObservable("keyup")

One the key event fires, we need to project that it happened and return the current searchInput value which contains our search term. 

    .Select(function(_) {
        return $("#searchInput").val(); })

Then, we’ll need to slow down the response to the request to Wikipedia so that we’re not constantly bombarding their server, but instead wait until an interval before firing and ignore all that happen during that interval.  To do that, we’ll make use of the Throttle function:

function Throttle(
    dueTime); // Ignores values which are followed by another
              // value before the due time

In this case, we’ll use 250 milliseconds as our interval time.

    .Throttle(250)

Next, we’ll take the observable and project our search term to return our searchWikipedia observable.  What this returns to us in C# parlance is an IObservable<IObservable<string>>. 

    .Select(function(term) {
        return createSearchRequest(term); })

We’ll need to flatten this, but only take the first value since it’s a single request.  To do that, we’ll need to use the Switch function which transforms an observable sequence of observable sequences into an observable sequence producing values only from the most recent observable sequence.

    .Switch();

Below is the complete code to create the observable which searches Wikipedia and then returns an array of values as the result.

var searcher = $("#searchInput")
    .ToObservable("keyup")
    .Select(function(_) {
        return $("#searchInput").val(); })
    .Throttle(250)
    .Select(function(term) {
        return searchWikipedia(term); })
    .Switch();

Now we can populate the unordered list by subscribing to our searcher.  As search result comes back, we want to clear the results, and then iterate through our array to add an item to the list.  Also, we can handle errors by simply pushing the exception value to another area for display should one occur.

searcher
    .Subscribe(
        function(data) {
            $("#results").empty();
            $.each(data, function(_, value) {
                $("#results").append("<li>"+value+"</li>");
            });
        },
        function(error) {
            $("#error").html(error);
        });

Let’s take a look at this in action.  I’ll search for Matt to start which returns the following results.

image

When I enter the next key, an “h”, my results refresh with the following.

image

As each letter comes along, then our results refresh based upon Wikipedia thinks we might be looking for.  And there you have it, a simple Wikipedia autocomplete autocomplete/lookup scenario as accomplished with the Reactive Extensions for JavaScript.

Conclusion

Through the use of the Reactive Extensions for JavaScript, we’re able to perform AJAX calls and then compose it together with our key-up to create a dictionary lookup/autocomplete scenario. 

This of course is only scratching the surface of what capabilities this library has and there is much more yet left to cover.  The question you’re probably asking now is where can I get it?  Well, for that you’ll have to stay tuned to Erik Meijer and his Reactive Extensions for JavaScript session at Mix on Wednesday.

What can I say?  I love JavaScript and very much looking forward to the upcoming JSConf 2010 here in Washington, DC where the Reactive Extensions for JavaScript will be shown in its full glory with Jeffrey Van Gogh (who you can now follow on Twitter).  For too many times, we’ve looked for the abstractions over the natural language of the web (HTML, CSS and JavaScript) and created monstrosities instead of embracing the web for what it is.  With libraries such as jQuery and indeed the Reactive Extensions for JavaScript gives us better tools for dealing with the troubled child that is DOM manipulation and especially events.

5 Comments

  • Can you please give us the source code of this article?

  • Under what conditions will the XmlHttpRequest(url) fail? I've tried getting this example to work several times but every time the response from the request is an empty XmlRequest Object.

    var response = eval(result.responseText);
    alert(response == null); // true

  • Hahahaha. I’m not too brhgit today. Great post!

  • What a joy to find someone else who thniks this way.

  • Word - Perfect Lightning is probably the least well-known application in the Word - Perfect Office X4 suite.
    The wrinkled sea beneath him crawls;He watches from his mountain walls,and
    like a thunderbolt he falls. Lightning also splits apart
    molecules in the air and by doing so makes nitrogen available to plants.

Comments have been disabled for this content.