📜 ⬆️ ⬇️

RxJS: Reactive Extension for Front End Development

Hundreds of articles have already been written about reactive programming. The frontend could not avoid this trend, but interest in the subject is still very, very high. Therefore, we just could not not interview one of our future speakers.

So, I beg to love and favor, Victor Rusakovich . Originally from Minsk, works for GP Software.travel.
Victor has been engaged in (mainly) front-end development for the last five years. Well, I started, like most of us, with jQuery.

Then there was a backbone, angular v1. For the last six months he has been working on a project on Redux / React.js (they are often confused with RxJS, but this is a bit different).
')


Reagent is actively used in your project. Can you explain what it is and how this movement began? Now everyone has heard of RxJS, RxJava, RxPython, RxBasic, well, except that RxBrainfuck is not.



Indeed, one of my previous projects was thoroughly penetrated using the RxJS library. All AJAX requests, working with DOM events, sometimes just processing static data - all this went through RxJS.

First, a few words about “reactive programming” as such. For example, in life you encounter “reactivity” in Excel:



As you can see, cells with formulas were created to automatically calculate the amount. In the reactive programming language, this can be represented as two data streams, gross and taxes, and a third net stream, which will collect data from gross and taxes and aggregate them using our formula, turning it into a final value.
I will use a very convenient online editor to show all my examples. This editor is good because it directly in the browser shows the result of the application. Well, the coolest feature of the radar is that later all snippets will remain available via a direct link. My first example is here .

var gross = Rx.Observable.just(5000) var taxes = Rx.Observable.just(13) var net = gross.combineLatest(taxes, (g, t) => g - t / 100 * g) net.subscribe(money => document.getElementById('out').value = money) 


On the Internet you can find many options for the definition of "reactive programming": in Wikipedia, here, on Habré. The topic is serious, even there is a special manifesto that can be signed, if you agree with his ideas - just why? Personally, I don’t like all these definitions, and I came up with my own:
Reactive programming is when you, instead of processing events one by one, combine them into a stream and then you only work with it.
(Date, Signature, Stamp).




If we talk about how it all started, the story of the emergence of RxJS is.
In 2010-2011, the guys from Microsoft, who worked with .NET, decided that it would be nice for JS to make a reactive library. The fact is that in .NET LINQ has long been popular. For example, like this , using LINQ, you can calculate the number of occurrences of a certain word in a string.

  string searchTerm = "data"; //Convert the string into an array of words string[] source = text.Split(new char[] { '.', '?', '!', ' ', ';', ':', ',' }, StringSplitOptions.RemoveEmptyEntries); // Create the query. Use ToLowerInvariant to match "data" and "Data" var matchQuery = from word in source where word.ToLowerInvariant() == searchTerm.ToLowerInvariant() select word; // Count the matches, which executes the query. int wordCount = matchQuery.Count(); 


We were lucky to start working with the very first version of the library. The code was still not in GitHub, but in some Microsoft's own repository. In addition, the features of the license did not allow to include in the project an unminified version. Documentation was a huge problem - you had to read articles written for .NET and try to understand at the concept level, despite differences in languages. It was then that I realized that I could write in any programming language.

How did you come up with the idea of ​​using RxJS?



Each project has its own characteristics that influence the choice of a particular technology. The decision may be due to the complexity of the interface, the presence or absence of an intelligible Roadmap, which shows that the project will develop and become more complex for at least several years. And in 2012 we could not find anything else similar to RxJS. Good technical support was important to us, and we succumbed to the Microsoft brand.

Why did we need RxJS at that moment?
Imagine an application with many independent UI components.
Now we add 10 API requests here (from authorization to product price checking). That's it.
Then we group the components in View so that some are used in different View, and some are not. Good at it.

Now we need to teach the components to change their state between requests. Somewhere to show a layer with a spinner, somewhere to hide the data, when an erroneous query returns. Moreover, a component may depend on several APIs and, moreover, sometimes it is not a single request that matters, but a series of requests and their responses. And the cherry on our cake is on the street in 2012, there is no Angular, Backbone is not suitable - it means that we will work only with jQuery. Without framework.

RxJS fit perfectly. We stopped catching separate events and building huge pyramids of callbacks. What is the pyramid of the callback does not need to explain, I hope?

Instead, between the components, we have data streams from which we could create new streams needed in a specific situation. For example, we have a stream with the choice of a product. If the user adds something to the cart, then an event appears in this thread with the product added. If the user deletes the product, an event with an empty array appears in the stream. Suppose we want the table to blink red every time something is removed from the basket:

 var cart = require('streams/cart') var removalsFromCart = cart .bufferWithCount(2,1) .where(history => history[1].length < history[0].length) removalsFromCart.subscribe(() => $('table').setClassFor1Sec('warning)) 

Link to snippet .

.bufferWithCount () will take the previous and current events and pass them an array further. In .where () we check that the current basket (it will be the second in the array after .bufferWithCount) contains less items than the previous one. If the condition is true, then the data is passed on to the .subscribe () method, which is the target of each event in the stream. If it were not for the use of the .where () method, then every change to the basket would cause a blink.

Hence, the reasons were just such. What do you think, and for what other reasons does it make sense to start using a reactive approach in projects?



At the very beginning, we all turned events into Rx.Observable. Over time, we realized that this is not always justified. For example, if we are 100% sure that clicking on this button will reload the page, then no additional changes will be required on the page. Now we handle such simple and unrelated events without RxJS.

But as soon as you need to keep track of many events, you cannot do without RxJS.
For example, it can be web-based sites that generate huge amounts of data.
These can be animations that start when one request is received, and when finished, should launch the next request.

But what we really love about RxJS for is that when writing all of these .where (), .buffer (), .map () and other methods, it doesn’t matter to us what is the source of the data. This can be an array or a web socket, which can send 100 objects per second, and then suddenly stop for a minute. All these events are equal for us and are treated the same.

And this means that, having dealt with asynchronous things, we can start using RxJS to process absolutely synchronous data, for example, mark all external links with bold:
 Rx.Observable.from(document.querySelectorAll('a')) .where(el => el.getAttribute('href').indexOf('http') === 0) .subscribe(el => el.style.fontWeight = 'bold') 


Link to snippet .
Summarizing, I would say that, as it seems to me, RxJS is ideal for projects with large streams of data to which you need to react - games, chat rooms and simple sites that have some complex updates on the page. Not for nothing, I think, RxJS included in Angular 2.

What other solutions are there for JS?



Immediately recalls several alternatives. First of all it is BaconJS. The library was created at about the same time as RxJS. Interestingly, in one of the projects we even tried to choose between RxJS and Bacon - that was about 4 years ago when both libraries had just been released. But then the choice leaned toward RxJS, since Bacon lost by the number of standard methods and the simpler API as a whole. Well, another important factor, as I said, was that only Juha Paananen was engaged in development and support, and Microsoft was behind RxJS. Today, you can use BaconJS without any concerns, because a good community has already been formed, the API is well documented, and many excellent examples can be found.

The next alternative is KefirJS (there are still words in the language to which JS has not been added? :). A wonderful library for reactive programming, supported by our compatriot Roman Pominov. Roman created KefirJS , trying to take the simplicity of the API from BaconJS (compared to RxJS) and immediately correcting errors in performance. And you know, it turned out well! For example, we use kefir every day in one of the projects.

Is it all so rosy? Can you just take and use these frameworks?



There are nuances.
About 3 years ago, after a report on RxJS at the conference, they asked me: “Did I understand correctly that in order to use reactive programming, you need to change your way of thinking?” This was the most correct question for all my reports! Very often it was read in the eyes of listeners, but asked only once. And the answer is: "Yes!"

The reactive approach is very different from how we used to write programs. Now we must first write the code that will describe the paths for passing events, and only then start these events in the program, where they will automatically trigger the necessary actions.
This is the first problem.

The second problem is that it is sometimes difficult to understand exactly which method can be applied in a particular case. For example, you turned some scalar data into queries. How to get access to the server response now? Suppose you read the description of all the methods in RxJS and even memorized .switch (): "From the most recent observable sequence" ...
Well, you understand - without jsfiddle can not figure it out.

It is difficult to deal with this, it will be necessary to survive the moment while the API knowledge is not enough for non-stop coding. This is where the rxmarbles.com project comes in handy - its author (André Staltz) has created a large number of dynamic time diagrams, which can be used to see how the order of the data affects the final stream. However, the .switch () method was not found there.

Fortunately, there is reactivex.io/documentation/operators/switch.html , where you can find a detailed and human description of the main methods and their timing diagrams, and switch () including:



It can be seen that the .switch () method returns data from nested threads. And, importantly, the data from the nested stream goes to the output until a new nested stream appears, which will soon start producing data: note that the yellow circle has not passed, although the yellow triangle has not yet appeared.
This is the method we usually use when working with ajax - as soon as a new request is sent, the data that can be returned from the previous request is not interesting for us. Now we will never see the outdated server response.

It turns out that with proper skill and desire it is quite possible to work with this and use it in production. Where to start and what resources can I read?



Today, a lot of resources. Only resources with links to dozens of resources, for all tastes: someone loves video courses, someone - reading documentation with examples, give someone books. I would start from this list:





I hope that you have aroused the desire to throw away the imperative approach and finally begin to follow the reactive paradigm! Stop pulling data! Let the data themselves go through the created chains!
By the way, the report for holyjs.ru is ready, there are minor improvements. In the report, I will tell you with examples about the practical application of RxJS in your projects. So see you in Petersburg at the conference on June 5th!

Source: https://habr.com/ru/post/302284/


All Articles