Journey into the world of RxJS – Observable

Standard
Spread the love

RxJS – in the beginning, I found it hard to understand what this library does. Just another fancy collection of functions OR someone infatuated with functional programming created this stuff. I tried to get familiar with it and soon I felt – no its not meant for me. It’s just too difficult to understand what all these functions are doing. I could see that the functions can be chained together and do something. But because I have spent too much of time in Procedural/OO world, the idea of dealing with functions and wiring them together to create meaningful stuff – Somehow I just couldn’t digest the thought. It’s true, I was an idiot to have an opinion like that.

A simple introduction to RxJS

Banging my head

Whenever I find a subject is too difficult for me to grasp [and that happens quite often 🙂 ], I have made a rule of spending lot of time in doing research, reading articles, trying out examples. This somehow helps me to get closer to the topic and crack the concepts.

As I said, working with RxJS was not a walk in the park. I could understand what Observables are meant for and how they differ from Promise. But map, exhaustmap, switchmap, etc. that was too much. After a long struggle and working on numerous examples, I finally got a rhythm of RxJS and believe me, I couldn’t hold my excitement. Every time I think of writing some code, a thought always comes to my mind as to how can I make use of RxJS functions to make it simpler and better.

If you are thinking like me that RxJS is too difficult, don’t worry – I will be trying to uncover the beauty of RxJS. Starting from basic concepts of Observable, we will move ahead with various functions that the library offers and also walkthrough some examples leveraging the full potential of RxJS.

Observable Vs Promise

I believe you must be already aware of Promises. Yes, the promise which once made will either be fulfilled or it won’t. I guess that’s the simple definition of it 🙂 Anyways here is how it looks like in JavaScript

const hello = new Promise((resolve, reject)=>{
resolve('hi!!!');
});

hello.then(v=>console.log(v));

Pretty simple huh!!! You can write your logic inside the nested function and based on the results either invoke resolve or reject. As per the above implementation, “hi!!!” will be printed on the console.

So if we have a Promise, why do we need observables? Well, If you are aware of the Observer pattern, you already know that some objects have a tendency of emitting a series of messages over its lifetime. For e.g. a Progress bar may return its progress each time it increments its value, or an HTTP request will emit messages indicating its internal state (message sent start, bytes uploaded, a response received, error, etc.) Under such circumstances, Promise won’t be an ideal choice, you need a special routine to broadcast messages and somehow a mechanism to indicate its final state – either successful completion or error. This is where Observable comes very handy.

Observable

Let’s rewrite the above example using Observable.

const obs$ = new Observable((observer)=>{
observer.next('hi!!!');
observer.complete();
});

obs$.subscribe(v=>console.log(v));

You can see that we have imported Observable from RxJS library. Instead of resolve, reject you now get an instance of an observer. Pass the message to an observer using the next method. Unlike Promise wherein you can call resolve method once, next can be used as many times as you want. But make sure you don’t call it after calling complete method. Once your code reaches the desired state and there is no more need of passing any messages, you must call complete method. The method indicates that the Observable has completed its job. In case of HTTP call, it could be a state wherein the code has received a response and it can be finally returned back to the caller.

Observable – next, complete, error

The code inside a subscribe method, is invoked each time observable emits a value. But as I described before, Observable also has two more states – complete and error. You can simply get access to these states in subscribe method. Refer below code

obs$.subscribe({
      next: v => console.log(`Value received ${v}`),
      complete: () => console.log('Completed observable.'),
      error: e => console.log(`An error occurred ${e}`)
});

You will notice that next and error each receives one argument for a function, while complete doesn’t. If everything works as expected and Observable completes its job, the complete function will be called (Note the call to the complete in Observable code). Any logical/explicit error will result in the invocation of the error function.

Subscription

The story of observable has just unfolded. What happens when you receive a series of messages in the next function and at some point, you wish to stop receiving messages? What if you don’t want to wait for the complete function to be invoked? Can you somehow instruct Observable that your observer is no more interested in listening to the messages?

Subscription – is the answer to all the questions above. When you subscribe to an Observable, an instance of Subscription is returned.

const subscription$ = obs$.subscribe(v=>console.log(v));

The Subscription instance has a handy method unsubscribe to stop receiving more messages from Observable. It is also a recommended practice that you must call unsubscribe on any active subscription that you have before destroying the component (look for subscription leaks).

We have barely scratched a surface of RxJS. In upcoming articles, we will go through some awesome functions and also unearth best practices. Meanwhile, create a new Angular project and install RxJS to try out the above examples.

Have a nice day and Build Something!!!

Leave a Reply

Your email address will not be published. Required fields are marked *