WARNING: I assume that you know basics of asynchronous programming, if not then please read this before going any further: Asynchronous Concepts
So, what’s RxJs?
According to the documentation:
RxJS is a library for composing asynchronous and event-based programs by using observable sequences. It provides one core type, the Observable, satellite types (Observer, Schedulers, Subjects) and operators inspired by Array#extras (map, filter, reduce, every, etc) to allow handling asynchronous events as collections.
In simple words, RxJs is a library which helps you in working with asynchronous tasks, events and streams and it does that by sharing some useful classes like aforementioned Observable and a ton of cool operators (due to my desire of keeping this post relatively short I am going to present only 5 operators that I find the most useful in my everyday work). Actually, RxJs has been so helpful to the Angular community that the Angular team decided to include it into Angular itself with the 6th version.
We are going to focus on Observables this time. Observable is a class that allows you to listen for events. To retrieve data from an observable you need to subscribe to it, when you do that it listens for events happening, so when they happen, you get the data. You can get more details on observables here: https://rxjs.dev/guide/observable.
Now let’s discuss 3 most common situations where developers are using Observables
All HtttpClient methods are returning Observables and that is of course because it takes time for a server to process and return the data (or just return in case you’re sending a get request). That means that http request operation is asynchronous.
Observables enable you to easily listen for DOM events like click or keyup. To listen to them you should use the fromEvent function that creates an observable accordingly. Here’s how this looks like:
(Remember that if you want to receive the actual data you should subscribe to it by adding .subscribe() before semicolon)
Another very common use case for using Observables is using them with some kind of store, like NgRx or NgXs. Stores like that usually share observables in order to keep watch over the state of the application.
Now since you know the very basics like why and how, let’s get to the useful interesting stuff that can be one with RxJs operators.
In our examples we are going to use simplest observable possible:
const obs$ = from([1, 2, 3]); (dollar sign at the end of the variable is a naming convention used to singlaize that the variable is indeed an observable)
How to use operators?
Easiest way to use operators is by putting them inside a pipe. Pipe runs a function for every stream element passing by the operator, and operators are the functions that can be used within it.
First operator is the first operator that we’re going to talk about (got the pun?). Most operators have self-describing titles and this case is no different. First operator basically allows you to listen for the first returned value of the observable and then stop (note that it is completely useless combined with Http requests that return the value once anyways)
obs$.pipe(first()).subscribe(numbr => console.log(number));
Code above prints only 1 because it’s the first event emitted, 2 and 3 are ignored.
Another useful operator worth mentioning is tap. Tap allows you to perform some kind of side effect for every event emission. For example you can log something or assign data to a variable (note: if you are using .subscribe it is basically the same thing).
obs$.pipe(tap(numbr => console.log(number))).subscribe();
Code above prints 1, 2 and 3 because tap is triggered for every emitted value.
Map is working the same way as in arrays. So it basically allows you to change structure of returned data. For example, let’s try to multiply every value returned by 2
obs$.pipe(map(numbr => numbr * 2)).subscribe(value => console.log(value));
The code prints 2, 4 and 6 just as expected.
StartWIth allows you to decide what first value is going to be. It is useful when you want to trigger the observable before the first event emission.
obs$.pipe(startWith(999)).subscribe(value => console.log(value));
Printed values are: 999, 1, 2, 3.
SwitchMap is used mainly in typeahead cases but not limited to them. What it does – it cancels previous request when a new event arrives. In real life case you would for example listen for changes on the input and filter a table while typing (previous result is not relevant).
To present switchMap fully – this time we are going to use a different example. Observable is going to be created out of DOM event keyup.
const another$ = timer(1000); fromEvent(document, 'keyup').pipe( switchMap(() => another$) ).subscribe(() => console.log('log'));
What happens here is: After you click a button on keyboard, wait 1000 ms and then log a message. Now what happens ,if you click button 10 times quicker? Only one message is going to be logged, and that is because switchMap cancels previous timers leaving only the most recent one.
We went over 5 most useful operators in my opinion, described what RxJs is and discussed common use cases. I hope that this article will help you in your next project and interest you in exploring RxJs more 🙂