Road To Angular 2 – Reactive Programming (RxJS)

Welcome to the first stop on the Road To Angular 2! The new version of Angular isn’t as simple as the previous one. It introduces a lot of new, hot and trendy stuff, so you have to prepare yourself before reaching the final destination!

In this series we’ll introduce you to:

  • Reactive Programming
  • ES6 features
  • TypeScript
  • Main concepts of Angular 2 apps
  • Integrating Angular 2 with Symfony backend

Today I’m going to tell you about Reactive Programming using RxJS, are you ready? Let’s start!

RxJS – why? It isn’t Angular 2, right?

Angular 1 is famous for its simplicity. It includes a lot of necessary features, so we don’t have to use jQuery for XHR communication, for example. As a result, it doesn’t force us to include external libraries. The Angular team has changed their attitude. Microsoft technology (TypeScript) and RxJS are included in Angular 2. As you can see, we have to get to know these technologies before learning our favourite framework.
Reactive programming is a subject important not only for JavaScript Developers, but also for every developer who wants to include asynchronous events into their apps. Rx isn’t only for JavaScript. There are versions for .Net, Java, Python and many others. So, I’d like to encourage you to read this article even if you don’t know JavaScript.
Let’s dive in…

Callback vs Promise vs Observable

JavaScript is a language which offers a few approaches that support handling asynchronous events, so let me just remind you what the difference is between those methods.
If you feel comfortable with callbacks and promises you can simply skip this part.
Callback is technically a function which we pass as a parameter into another function, but what’s more important is that it isn’t executed immediately, but right after the parent function is complete. It gives us the freedom to manage asynchronous events as we want.
https://jsfiddle.net/q288pfb1/7/
As you can see in the example, we get data from the server using Ajax and we pass callback as a parameter. In the callback, we retrieve the response and pass objects to another function in which we insert some items into the list. Easy, right? Is it pretty? Nope!
Have you ever heard of callback hell? It looks like this:

It just isn’t readable.
I promise that there are better places to live in than Callback Hell, one of them – for sure – is Promise Heaven!
Of course we can deal with callback hell but it isn’t main topic of this article. You can read more here: http://callbackhell.com/
Most readability problems can be solved with promises. ES6 introduces the Promise object as an object in JavaScript. Before this, we had to deal with external libraries like jQuery which offered such objects.
A brief reminder. Promise has three states:

  • pending – when initializing object – “Hello, I really want to do something, I promise, but it can take some time, just wait”
  • fulfilled – after function has completed – “Hi! I finished my work and everything is alright, mate!”
  • rejected – meaning – “Something went wrong, sorry”

The same code, but written using Promise, looks like this:
https://jsfiddle.net/y9czkyoc/4/
To put it simply, Promise is an object which can be rejected or resolved. After fulfilling we can process returned data using the then() method. Promise is a set of callbacks under the hood. If you are interested in implementing it, I encourage you to read this article: https://www.promisejs.org/implementing/
As we are talking about Angular, promises are ubiquitous. When we want to get data using Ajax we use the $http service which returns… promise represented by $q object! Our Angular services often look like this:
http://plnkr.co/edit/rUmN1rwPA3795Hytw6R3?p=preview
When I sat down to Angular 2 without documentation, I was surprised that my then() function didn’t work with object returned from http service. What is more, the construction http.get() didn’t make a request. Then I realized that the returned object type is Observable.
Quoting the documentation: “The return value may surprise us. Many of us would expect a promise <that’s the point>. We’d expect to chain a call to then() […] Instead we’re calling a map() method. Clearly, this is not a promise.”
…and so it began… Angular 2 uses a special and trendy reactive way to solve asynchronous methods, which looks like this:
return this.http.get(thistechnologyUrl)
               .map(res => res.json().data)
               .catch(this.handleError);
Before I explain these lines of code, I want to describe what reactive programming means.
Remember React.js !== RxJS

Why does Angular 2 use RxJS? Are promises out of fashion?

A few years ago, web applications weren’t as interactive as they are now. Only asynchronous action was used with the form submit button. Now the situation is a bit different. Often, we want to use many asynchronous actions at the same time. The answer to this problem is reactive programming, which can deal with it. In this situation, we have to change our thinking. In reactive programming, everything is an asynchronous data stream. What does this mean?
It’s likely all of us have used an asynchronous data stream without even realizing it. Are you familiar with code like this?
object.addEventListener("click", function(){
    // Do something after clicking
});
Yes? You often use it, and an asynchronous data stream is equal to such actions, but with additional features. We can say that this stream from reactive programming is an array which contains some values returned by a function over a period of time. As it is an array, it gives us a possibility to use the advantages of functional programming. Often, streams are illustrated like this:

On the top we have one timeline (representing the asynchronous data stream) on which there are some values generated by events. Below the top timeline there is a block representing the functions which, for example, map/filter this stream and return new stream with desirable data.

There are a few definitions you have to know before analysing the code:
Observer pattern – Technically, it is said that there are two types of objects: one of them is called Observable which sends signal/notification to objects called Observers. Observers can react to this signal.
In RxJS, subscribe is a method to listen (observer). The subscribe function gets 3 parameters which are callbacks. The first of them is called onNext and it is passed when value is emitted from Observable. The second one is onError which is passed when something goes wrong (for example status 500 from the server). The last parameter is onCompleted – it’s passed when a stream finishes work.
A lot of people claim that Observables are “lazy”, but what does that actually mean? As I said at the beginning, I was surprised when I wrote http.get() in Angular 2 and it didn’t make a request to the server. This is the difference between Observables and Promises.
I will illustrate it using a simple analogy:
Observables are like the guys who don’t “talk” when nobody wants to listen. They are ready to talk as long as somebody is interested in listening. What is more, they’re smart – and they stop talking when listeners signalise that they don’t want to listen anymore.
Promises think differently, they have only one thing to say and they have to hurry because their lives are short, so they start talking right after they’re born… ‘till they die. We cannot stop them.
Some code illustrating this analogy:
https://jsfiddle.net/wwLkvzbj/4/
Analyse this code and try to understand it. As you can see, promise started working at the beginning where it was declared, but observable started working when the first subscriber/listener appeared. Furthermore, values of observable change over time – different listeners have different values. Promise after resolve cannot be changed or cancelled but observable has these features.
If you aren’t convinced of using Observable you can still use promises in Angular 2. Basically, they convert observable into promise, so would it make sense? Maybe in some situations. This code shows how can you do it:
return this.http.get(this.technologiesUrl)
                .toPromise() // This line convert Observable into promise
                .then(res => res.json().data, this.handleError)
                .then(data => { console.log(data); return data; });

Should we use RxJS in Angular only for server communication?

There are some cases where we can take advantage of reactive programming. It is a good idea when have a lot of asynchronous actions over which we want to have full control. Imagine that you’re writing a web IDE. You want to add autocompletion and hinting syntax. It isn’t good idea to make a request to server every time you fire event keydown – requests will kill your server and slow your application. In this situation, people will be punished for their fast writing and your startup will be ruined. What’s more, you plan to give clients useful shortcuts. There will be combinations of mouse and keyboard events (sometimes connected with request to the server). Using the traditional way you’ll have to:

  • add some variables to control state
  • manually take care of timeouts and clear them
  • spend time to manage code properly for shortcuts

Reactive programming can help you solve these problems. Try to think how you would do it with and without reactive programming. It’s a good exercise.

Conclusion

Reactive programming is difficult and it requires us to change the way we think about solving problems. The topic is so wide that I only managed to scratch the surface of RxJS in basic Angular 2 usage. I think the effort to understand reactive programming will be rewarded in the future.
Some recommended reading:

See you soon at the next stop, ES6 and TypeScript!
 

Pidätkö tästä artikkelista?
Tägit
Jaa
How can we help you start your new digital project?
You can select more than one answer.
Are you looking for any particular skills?
You can select more than one answer.
Let us know, how we can reach you
* Required fields
Miten voimme auttaa digitaalisen projektin aloittamisessa?
Voit valita useamman vastausvaihtoehdon.
Etsitkö tiettyä taitoa?
Voit valita useamman vastausvaihtoehdon.
Kerro meille kuinka voimme tavoittaa teidät
* Pakolliset kentät