Matthew Podwysocki

Sponsors

The Lounge

Wicked Cool Jobs

News

Advertisement

Introduction to the Reactive Extensions for JavaScript – Composing Callbacks

So far in this series, we’ve covered some basic information about the Reactive Extensions for JavaScript (RxJS) including creating observables and creating observers as well as jQuery integration.  Now that we have a foundation in some of the basic building blocks, let’s actually do something interesting with it.  For example, how would we compose two AJAX calls together with callbacks?  In this post, we’ll explore using the Bing Translator in combination with jQuery and the RxJS.

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

Detecting and Translating Text with the Microsoft Translator

One of the many examples I’ve played with involving asynchronous programming, especially with my F# samples as well as the Reactive Extensions for .NET is using the Microsoft Translator.  This API, which is provided in several flavors (SOAP, AJAX and HTTP) allows us to not only translate but also detect the language of a given piece of text.  Just as well, there are other functions such as getting all languages codes and getting all language names by language code, and we’ll cover that in a subsequent post.  Getting started, you need to apply for a developer key which you can get here.  From there, we can embed our JavaScript link in our HTML so that we can get started.

<script type="text/javascript"
        src="http://api.microsofttranslator.com/V1/Ajax.svc/Embed?appId=myAppId">
</script>

In this example, we’re going to first detect the language of the given piece of text and then translate it into another language.  In honor of Erik and his team, I decided on Dutch as the destination language.  In order to detect the language we need to call the detect function which looks like the following.  It takes in some text and then a callback which then will give us our result as the function parameter.

Microsoft.Translator.detect(
    text,      // Text of the unknown language 
    callback); // A callback on complete

Next, we need the ability to translate our text to Dutch once we’ve determined the source language.  In order to do so, we must call the aptly named translate function which we provide our text, a from language that we’ll provide from our detect function callback, our destination language and finally a callback which provides us with the resulting text.

Microsoft.Translator.translate(
    text,      // Text to translate 
    from,      // The source language
    to,        // The destination language
    callback); // The handling callback

What you’ve noticed from these two functions is that they provide callback functions for each.  If we want truly compositional behavior, our code could get quite messy especially if we’re doing anything such as filtering results, transforming, aggregating and so forth.  But for now, we’ll have a simple example of composing these callbacks together.  In order to do so, we have to turn these two functions, detect and translate into Observables.  So, how do we do that? 

In this case, we’ll make use of the AsyncSubject class which allows us to represent the result of an asynchronous operation.  This class will take one value and only one value and then caches it for all future calls and acts as both an Observer and an Observable.  So for each time we call this subsequently, it will not cause a side effect and instead yield us the cached calculated value.  We’ll then call the detect method with our text and a callback, and inside of our callback, we’ll yield the value with OnNext and then mark our sequence as completed by calling OnCompleted.  Finally, we’ll return our AsyncSubject as an Observable and hide the fact that it’s both an Observer and Observable.

function detect(text) {
    var subject = new Rx.AsyncSubject();

    Microsoft.Translator.detect(
        text,
        function(result) {
            subject.OnNext(result);
            subject.OnCompleted();
    });

    return subject.AsObservable();
}

The same also applies to our translate function in pretty much the same form as we have above.

function translate(text, from, to) {
    var subject = new Rx.AsyncSubject();

    Microsoft.Translator.translate(
        text,
        from,
        to,
        function(translation) {
            subject.OnNext(translation);
            subject.OnCompleted();
    });

    return subject.AsObservable();
}

Now, let’s compose these together in such a way that we first detect the language of the text and then translate.  To make that happen, we’ll use the SelectMany method which projects each value of our observable sequence to an observable sequence and flattens the resulting observable sequences into one observable sequence.  In this case, we’re only projecting one value to the next observable sequence.

var translator = detect(translateText)
    .SelectMany(function(detected) {
        return translate(translateText, detected, "nl");
    });

Of course we could do more like filter, scan, etc with this, but it’s a good start.  Now bringing it all together in a jQuery and RxJS way, we can now complete our example by wiring up our HTML to take the input from a textbox once a button has been clicked, translate it, and display the result.

$(document).ready(function() {
    $("#translateCommand")
        .ToObservable("click")
        .Subscribe(function(event) {

        var translateText = $("#translateText").val();
        var translator = detect(translateText)
            .SelectMany(function(detected) {
                return translate(translateText, detected, "nl");
            });

        translator.Subscribe(function(translated) {
            $("#translatedText").html(translated);
        });
    });
});

And now we can see it in action by entering a sentence and sure enough it detects it as English properly.

image

How can I be sure of that?  What if I want to perform a side effect during the process, such as displaying our detected language?  To do that, we can use the Do method which invokes some sort of action for its side effect for each item in the sequence.  We could then change our translator Observable to the following to enable that behavior.

var translator = detect(translatedText)
    .Do(function(detected) {
        $("#detectedText").html("Detected " + detected);
    })
    .SelectMany(function(detected) {
        return translate(translatedText, detected, "nl");
    });

Now we have a nice compositional and quite fluent chain which deals with asynchronous behavior.  Invoking it this time in Spanish, we get the following result.

image

We could go even further to aggregate counts of which language was detected over time by using the Scan function, but that’s for another time.

Conclusion

Through the use of the Reactive Extensions for JavaScript, we’re able to bring compositional behavior to that which had been harder to do, such as asynchronous callbacks.  We’re able to get code in a nice fluent manner that makes sense and let’s us focus on the core problem domain instead of scattering code within a bunch of callbacks which can lead to any number of race conditions.

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.  I hope to have more announcements soon about its general availability.

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.


Posted Thu, Mar 11 2010 12:27 AM by Matthew.Podwysocki

[Advertisement]

Comments

uberVU - social comments wrote Social comments and analytics for this post
on Thu, Mar 11 2010 1:54 AM

This post was mentioned on Twitter by mattpodwysocki: Composing callbacks together using the Reactive Extensions for JavaScript for fun and profit: http://bit.ly/cqP1Q8 #RxJS

JavascriptBank.com wrote re: Introduction to the Reactive Extensions for JavaScript – Composing Callbacks
on Thu, Mar 11 2010 11:08 PM

very cool & good tip, thank you very much for sharing

Matthew Podwysocki wrote Introduction to the Reactive Extensions for JavaScript – From Blocking to Async
on Fri, Mar 12 2010 1:59 AM

We’ve covered a bit of ground already in this series on the Reactive Extensions for JavaScript (RxJS

Matthew Podwysocki's Blog wrote Introduction to the Reactive Extensions for JavaScript – From Blocking to Async
on Fri, Mar 12 2010 9:24 AM

We’ve covered a bit of ground already in this series on the Reactive Extensions for JavaScript (RxJS

Matthew Podwysocki wrote Introduction to the Reactive Extensions for JavaScript – Wikipedia Lookup
on Mon, Mar 15 2010 5:00 PM

We’ve covered a bit of ground already in this series on the Reactive Extensions for JavaScript (RxJS

Matthew Podwysocki's Blog wrote Introduction to the Reactive Extensions for JavaScript – Wikipedia Lookup
on Mon, Mar 15 2010 6:30 PM

We’ve covered a bit of ground already in this series on the Reactive Extensions for JavaScript (RxJS

Matthew Podwysocki wrote Introduction to the Reactive Extensions for JavaScript – Composing deeper
on Tue, Mar 16 2010 7:59 PM

We’ve covered a bit of ground already in this series on the Reactive Extensions for JavaScript (RxJS

Matthew Podwysocki's Blog wrote Introduction to the Reactive Extensions for JavaScript – Composing deeper
on Wed, Mar 17 2010 10:09 AM

We’ve covered a bit of ground already in this series on the Reactive Extensions for JavaScript (RxJS

Matthew Podwysocki wrote The Reactive Extensions for JavaScript Released
on Wed, Mar 17 2010 7:50 PM

The long awaited day has come as the Reactive Extensions for JavaScript have been released on DevLabs

Matthew Podwysocki's Blog wrote The Reactive Extensions for JavaScript Released
on Wed, Mar 17 2010 11:40 PM

The long awaited day has come as the Reactive Extensions for JavaScript have been released on DevLabs

Matthew Podwysocki wrote Introduction to the Reactive Extensions for JavaScript – Drag and Drop
on Fri, Mar 19 2010 1:36 AM

We’ve covered a bit of ground in this series, covering the basics, jQuery integration, blocking to asynchronous

Matthew Podwysocki wrote Introduction to the Reactive Extensions for JavaScript – jQuery Live Event Integration
on Sun, Mar 21 2010 7:33 PM

So far we’ve come a long way in this series, starting with some of the basics, and then going deeper

Matthew Podwysocki's Blog wrote Introduction to the Reactive Extensions for JavaScript – jQuery Live Event Integration
on Sun, Mar 21 2010 11:17 PM

So far we’ve come a long way in this series, starting with some of the basics, and then going deeper

Matthew Podwysocki wrote Introduction to the Reactive Extensions for JavaScript – Extending jQuery AJAX
on Fri, Apr 2 2010 7:10 PM

So far we’ve come a long way in this series, starting with some of the basics, and then going deeper

Matthew Podwysocki's Blog wrote Introduction to the Reactive Extensions for JavaScript – Extending jQuery AJAX
on Fri, Apr 2 2010 7:19 PM

So far we’ve come a long way in this series, starting with some of the basics, and then going deeper

Matthew Podwysocki wrote Introduction to the Reactive Extensions for JavaScript – A Separation of Concerns
on Fri, Apr 9 2010 12:46 AM

So far we’ve come a long way in this series, starting with some of the basics, and then going deeper

Matthew Podwysocki's Blog wrote Introduction to the Reactive Extensions for JavaScript – A Separation of Concerns
on Fri, Apr 9 2010 1:03 AM

So far we’ve come a long way in this series, starting with some of the basics, and then going deeper

Matthew Podwysocki's Blog wrote Introduction to the Reactive Extensions for JavaScript – Aggregation Part 1
on Wed, Apr 14 2010 1:50 AM

So far we’ve come a long way in this series on the Reactive Extensions for JavaScript , starting with

Matthew Podwysocki wrote Introduction to the Reactive Extensions for JavaScript – Aggregation Part 2
on Wed, Apr 14 2010 8:53 PM

So far we’ve come a long way in this series on the Reactive Extensions for JavaScript , starting with

Matthew Podwysocki's Blog wrote Introduction to the Reactive Extensions for JavaScript – Aggregation Part 2
on Wed, Apr 14 2010 10:12 PM

So far we’ve come a long way in this series on the Reactive Extensions for JavaScript , starting with

Matthew Podwysocki wrote Introduction to the Reactive Extensions for JavaScript – New Release and Joins
on Mon, Apr 19 2010 6:41 PM

This past week there was a new release of the Reactive Extensions for JavaScript which includes many

Matthew Podwysocki wrote Introduction to the Reactive Extensions for JavaScript – Going Parallel with ForkJoin
on Fri, Apr 23 2010 5:11 PM

This past week there was a new release of the Reactive Extensions for JavaScript which includes many

Matthew Podwysocki's Blog wrote Introduction to the Reactive Extensions for JavaScript – Going Parallel with ForkJoin
on Fri, Apr 23 2010 5:18 PM

This past week there was a new release of the Reactive Extensions for JavaScript which includes many

Matthew Podwysocki wrote Introduction to the Reactive Extensions for JavaScript – Refactoring a Game
on Tue, May 4 2010 7:07 PM

We’ve covered a lot of ground so far in this series including a lot of the combinators as well as the

Matthew Podwysocki's Blog wrote Introduction to the Reactive Extensions for JavaScript – Refactoring a Game
on Tue, May 4 2010 7:30 PM

We’ve covered a lot of ground so far in this series including a lot of the combinators as well as the

Matthew Podwysocki wrote Introduction to the Reactive Extensions for JavaScript – Async Method Chaining
on Mon, May 10 2010 11:22 PM

Recently, there was a blog post by Dustin Diaz about method chaining over asynchronous operations . 

Matthew Podwysocki's Blog wrote Introduction to the Reactive Extensions for JavaScript – Async Method Chaining
on Tue, May 11 2010 12:40 AM

Recently, there was a blog post by Dustin Diaz about method chaining over asynchronous operations . This

Matthew Podwysocki wrote Introduction to the Reactive Extensions for JavaScript – Custom Schedulers
on Wed, May 12 2010 5:27 PM

In the previous post , I talked a little bit about asynchronous method chaining and extending jQuery

Matthew Podwysocki's Blog wrote Introduction to the Reactive Extensions for JavaScript – Custom Schedulers
on Mon, May 17 2010 6:56 PM

In the previous post , I talked a little bit about asynchronous method chaining and extending jQuery

Matthew Podwysocki's Blog wrote Introduction to the Reactive Extensions for JavaScript – The Final Countdown Timer
on Mon, May 17 2010 6:59 PM

In the previous couple of posts, I’ve talked about asynchronous method chaining and creating custom schedulers

Demis Bellot wrote re: Introduction to the Reactive Extensions for JavaScript – Composing Callbacks
on Sun, May 23 2010 6:46 AM

"To make that happen, we’ll use the SelectMany method which projects each value of our observable sequence to an observable sequence and flattens the resulting observable sequences into one observable sequence.  In this case, we’re only projecting one value to the next observable sequence."

I think its sentences like the above that is hindering readability of an otherwise good series. Rx is a very nice succinct API but in order to take advantage of it I'm going to need a better idea of 'why' I need to do something.

With the above example I'm still not sure why we have to use 'SelectMany' since as far as I can tell where only producing 1-click => 1 detect language => 1 translate text. Given the previous assumption what would the effect be if we didn't use 'SelectMany'?

Also I'm lost as to why you need a separate 'Do' method chain when it looks like you could quite easily merge the:

>$("#detectedText").html("Detected " + detected);

In the 'SelectMany' method body? Again its more code to write and not obvious why we have to write it. I think having more code examples is definitely going to help.

Matthew.Podwysocki wrote re: Introduction to the Reactive Extensions for JavaScript – Composing Callbacks
on Mon, May 24 2010 2:45 PM

@Demis,

Ok, let's look at your questions each one at a time.

To think about why we'd use a SelectMany over Select is the following:

Remember, the signature of each, IObservable<T> and IObservable<U>.  To do that by default, you use a SelectMany, even if the observable sequence only yields a single value, else you use a Select and Switch which I've covered before.  

Now think your solution of using Select through here.  If I want to transform one observable sequence to another, using Select...

// IObservable<T> -> (T -> IObservable<U>) -> IObservable<IObservable<U>>

someOperation.Select(x => someOtherOperation(x))

The problem with that approach is that unless you have a Switch statement to return that single value, you now took a IObservable<T> and turned it into an IObservable<IObservable<U>>.  The Select and Switch is the same intent of the SelectMany with a single value.

The reason why I broke the Do into a separate step is the separation of concerns that I have.  I want my Do to only do one thing and I want my SelectMany to have the same intent, one thing.  To think about programming in Rx, we think about small composable steps.

Matt

Matthew Podwysocki wrote Introduction to the Reactive Extensions for JavaScript – Wrapping the Dojo API
on Fri, May 28 2010 3:35 PM

Recently in some of the comments I’ve received (keep them coming BTW), I get questions about taking existing

Matthew Podwysocki's Blog wrote Introduction to the Reactive Extensions for JavaScript – Wrapping the Dojo API
on Fri, May 28 2010 9:44 PM

Recently in some of the comments I’ve received (keep them coming BTW), I get questions about taking existing

Matthew Podwysocki wrote Introduction to the Reactive Extensions for JavaScript – MooTools Integration
on Fri, Jun 4 2010 10:59 PM

In the previous post, I covered a bit about how we’ve integrated the Dojo Toolkit into the Reactive Extensions

Matthew Podwysocki's Blog wrote Introduction to the Reactive Extensions for JavaScript – MooTools Integration
on Fri, Jun 4 2010 11:03 PM

In the previous post , I covered a bit about how we’ve integrated the Dojo Toolkit into the Reactive

Matthew Podwysocki wrote Introduction to the Reactive Extensions for JavaScript – Conditionals
on Wed, Jun 16 2010 5:36 PM

After spending the past couple of posts talking about how we integrate and why, let’s get back to the

Matthew Podwysocki wrote Introduction to the Reactive Extensions for JavaScript – Looping Operators
on Thu, Jun 24 2010 5:50 PM

After spending the past couple of posts talking about how we integrate and why, let’s get back to the

Matthew Podwysocki wrote Introduction to the Reactive Extensions for JavaScript – Error Handling Part I
on Tue, Jul 20 2010 6:20 PM

We’ve covered a bit recently with conditional and looping operators on the Reactive Extensions for JavaScript

Matthew Podwysocki wrote Introduction to the Reactive Extensions for JavaScript – Error Handling Part II
on Mon, Aug 2 2010 3:17 PM

We’ve covered a bit recently with conditional and looping operators on the Reactive Extensions for JavaScript

Matthew Podwysocki wrote Dojo Deferred and the Reactive Extensions for JavaScript
on Thu, Aug 12 2010 6:38 PM

We’ve covered quite a bit in this series including how well the Reactive Extensions for JavaScript plays

Matthew Podwysocki wrote Introduction to the Reactive Extensions for JavaScript – Buffering
on Wed, Aug 25 2010 6:56 PM

We’ve come a long way in the series on the Reactive Extensions for JavaScript .  After spending

Add a Comment

(required)  
(optional)
(required)  
Remember Me?
Devlicio.us