Want to use Observable Collections? Have you heard about Reactive Extensions? Like LINQ? Don't like writing spaghetti code? Need monads? And all this on javascript?
So what is Rx for JavaScript?
Rx stands for Reactive Extensions. As the definition on
the project
page says:
Rx is a library for creating asynchronous and event-oriented programs using collections, following the “Observer” pattern.
The main idea is to consider asynchronous computing as data sources. For example, a computer mouse is nothing but a source of clicks and cursor movements. To work with such a data set are
Observable Collections . Since RxJS takes roots from the .NET world, therefore, some
LINQ features (select, where, take, skip, etc.) become available to us. More on this later, but for now let's consider the structure of the library.
Integration with existing frameworks
First, download RxJS via the following
link . Included are extensions for working with jQuery, MooTools, prototype, Dojo, ExtJS, as well as with popular services like Google Maps. The library itself consists of a single rx.js file of 7.4 KB in size (30 KB in uncompressed form).

')
In the examples, Visual Studio 2010 with the Web Developer package installed will be used as an editor. Client framework - jQuery.So, create a simple HTML page and enable RxJS.
<head> <title>Samplestitle> <script type="text/javascript" src="Scripts\rx.js"></script> <head>
After this, IntelliSense will start showing Rx methods.

A bit of theory
Before moving forward, I would like to clarify some of the terms and conventions adopted in Rx.
- Observable is a collection, a data source that generates events and sends them to subscribers.
- Observer ("Observer") - the subscriber, which will process the signals from the source.
- It is the Observable that subscribes to the Observer events, but not otherwise.
- The basis of Rx is the theory of monads, albeit unrealized in the classical form. Their presence is expressed in "lazy" (pending) calculations, as well as the ability to cancel some of them. At this point we will discuss in more detail later in the article.
- Cold Observable is a source that sends new data to subscribers only after calling the Subscribe method.
- “Hot” browser (Hot Observable) - the source that sends the data even in the absence of subscribers. After calling Subscribe, clients start receiving data not from the beginning of generation, but only from the current moment. An example would be DOM element events.
- The names of the RxJS methods follow the CamelCase rule.
Observers
As mentioned above, the Subscribe method is used to subscribe to Observable events:
var source = null; var subscription = source.Subscribe( function (next) { console.log("OnNext: " + next); }, function (exn) { console.log("OnError: " + exn); }, function () { console.log("OnCompleted"); });
and
var source = Rx.Observable.Empty(); var observer = Rx.Observer.Create( function (data) { $(" ").text(data).appendTo("#content"); }); var handle = source.Subscribe(observer);
Consider the Subscribe method in more detail:
- Returns a link to the created / transmitted Observer.
- As the first overload, it takes up to three parameters: a handler for each element of the data array (OnNext); exception handler (OnError); completion handler (OnCompleted)
- In the second overload, the already created Observer is transmitted with the ability to control the OnNext, OnError, OnCompleted events.

To unsubscribe an observer there is no separate method. Instead, the Dispose pattern came to RxJS from the .NET environment.
So the link (handle) for Observer contains the Dispose method, by calling which you can destroy the object.

Observables
In most cases, you will always work with “hot” browsers: be it a web service call, or work with DOM elements. “Cold” browsers in real-world applications are not so common, but when unit testing, their purpose becomes clear - working with previously prepared data sets.
Below is the API table for creating Observable and their description.
Method name | Description |
Empty () | Returns an empty collection with OnCompleted call |
Throw (error_msg) | Returns an empty collection with a call to OnError |
Return (value) | Returns a collection from a single item. |
Range (start, count) | Returns an array of 32-bit Integer |
Generate (initial_state, condition, selector, iterate) | Returns a collection created by following parameters. |
GenerateWithTime (time) | Similar to the Generate method, but adds the time between the generation of elements |
Never () | Returns an empty collection without triggering events. |
toObservable (event_name) | Extension to work with the jQuery object |
FromArray () | Initializes a collection from a js array |
Create (subscribe_detail) | Creates a collection of observer subscription details. |
FromDOMEvent (dom_element, event_name) | Extension for working with DOM elements |
FromIEEvent (dom_element, event_name) | An extension for working with specific events of Internet Explorer's DOM elements |
FromHtmlEvent (dom_element, event_name) | Is a generic method for FromDOMEvent () and FromIEEvent () |
LINQ
So, we come to one of the most interesting features of RxJS - LINQ support. I think many have heard about this wonderful technology available on the .NET platform.
LINQ stands for Language Integrated Query, allowing you to query various collections. With the advent of RxJS, not all methods came to the world of JavaScript, but the most useful ones:
- Select (SelectMany)
- Take (TakeUntil, TakeWhile, TakeLast)
- Where
- Skip (SkipUntil, SkipWhile, SkipLast)
- Groupby
- Etc.
Added and new, present only here:
- DistinctUntilChanged - monitors the status of the collection. Events OnNext, OnCompleted will be triggered only when data changes.
- Do - provides access to new data before calling DistinctUntilChanged
- Throttle - sets the minimum time after which the collection will be tracked for new data
- Timestamp (RemoveTimestamp) - instead of transferring data management to an operator, a timestamp is transferred, after processing which the next operator is called
I will not give a complete list, because You can view the rest of the methods yourself.
For a clearer understanding of the picture below is a diagram of the event subscription:

Since jambda expressions do not exist in JavaScript, their role as parameters for LINQ methods performs normal functions:
var items = [1, 2, 3, 4, 5]; var observable = Rx.Observable.FromArray(items).Select(function (item) { return { Value: item, Sqrt: Math.sqrt(item) }; }).Where(function (item) { return item.Value + 2 < 5; });
Returning to the new features (DistinctUntilChanged, Throttle, etc.) I would like to note their extraordinary usefulness. So Throttle will replace your use of setInterval and setTimeout in some situations, and using it with DistinctUntilChanged will reduce, for example, the number of ajax requests when entering text.
And visual code for example:
var input = $("#textbox").toObservable("keyup") .Select(function (event) { return $(event.target).val(); }) .Timestamp() .Do(function (inp) { var text = "I: " + inp.Timestamp + "-" + inp.Value; $(" ").text(text).appendTo("#content"); }) .RemoveTimestamp() .Throttle(1000) .Timestamp() .Do(function (inp) { var text = "T: " + inp.Timestamp + "-" + inp.Value; $(" ").text(text).appendTo("#content"); }) .RemoveTimestamp() .DistinctUntilChanged(); var subscribtion = input.Subscribe(function (data) { $(" ").text("Your text: " + data).appendTo("#content"); });
Thus, before calling DistinctUntilChanged and transmitting an array of text field values, we perform some kind of logging.
Say no to spaghetti code!
In this last part of the article I would like to consider working with web services that have already been mentioned several times.
How many times have you written about this code:
$.ajax({ url: "your_url", dataType: "json", success: function (data, textStatus, xhr) { $("#results").empty(); $.each(data[1], function (_, result) { $("#results").append(" " + result + " "); }); }, error: function (xhr, textStatus, errorThrown) { $("#error").text(errorThrown); } });
I think quite often. What is his problem? That's right, the data processing logic is encapsulated along with the definition of the data source, which turns into a “spaghetti code”.
RxJS comes to the rescue of this problem. First you need to connect the file rx.jQuery, which is an extension for integration with jQuery.
After that we will do a little refactoring of the above code:
function serviceCall(text) { return $.ajaxAsObservable( { url: "your_url", dataType: "json", format: "json", data: text }); } var source = serviceCall("search me"); var handle = source.Subscribe(function (result) { $("#results").append(" " + result + " "); }, function (exn) { $("#error").text(exn); });
Thus, we have separated the data processing logic from the request itself, wrapping the request itself into an entity.
Afterword
This article wanted to show the power of the Reactive Extensions for JavaScript library. The scope of its application is quite extensive and is determined only by the needs of the programmer. From my own experience, I can say that the Observable Collections and the philosophy of RxJS itself require a revision of their already well-established code-writing practices, but it is worth it.
Unit testing, cancellation of operations, and the SelectMany operator (monads appear here) were not considered, but this will be discussed in the next article.
PS
A list of useful links that consider some points in more detail: