When looking at RxJS for the first time, some of the concepts might seam confusing, and strange, that’s because the library borrows ideas from two fundamentally different programming paradigms, object-oriented, and functional programming. In this post, I assume you know a little bit of both. A good understanding of higher order functions, and class-oriented programming can help you tremendously here.
RxJS is a JavaScript library for reactive programming, which is a programming paradigm concerned with dealing with change (reacting to it), RxJS enables this by implementing the Observer pattern, where observers can subscribe to an observable to be notified whenever the observable emits a new value.
The Observer Pattern
Let’s consider YouTube as an example implementation of this pattern, a viewer can subscribe to a channel in order to receive notifications whenever that channel releases a new video, in other words, the viewer observes that channel, and watches for new videos. In this case, the viewer is an observer, the YouTube channel is an observable, and the observable emits new videos to it’s subscribers.
One very important thing to notice is that the subscriber doesn’t know when the YouTube channel will release a new video, so it wouldn’t be a good idea for them to sit for hours in front of their screen waiting for a new release, instead, they can do other things, and when a new video comes out, they can watch it (react to it). A simplification of the above example might look like this in RxJS:
First, we create the channel
object, which is of type Observable
. The channel has 3 videos to release, and it sends them to each subscriber through the next
method.
We then create a viewer
object, which implements a next
method, which handles any incoming videos. Finally, we subscribe the viewer to the channel using the subscribe
method of the observable.
Operators
An operator is a function that can be used to operate on values emitted by an observable. For example, an operator can be used to filter the values emitted by the observable, or transform the values into something else. Consider this simple and rather trivial example:
- RxJS comes with a healthy amount of readily available operators, here we import two of which,
filter
, andmap
. - The
Rx.of
function is a function that creates an observable that emits all the provided values in sequence, which means that thenumbers
observable will emit the values 1 through 6.
Note: Observables van be created in many ways using functions such as from
and fromEvent
, which you can read about here.
isEven
is a simple function that tells us whether a number is even or not..evenNumbers
is an observable that emits every even number emitted bynumbers
. The filtering of numbers is done by thefilter
operator, which we imported fromrxjs/operators
. Thefilter
operator is very similar to theArray.filter
method in that it takes a predicate as an argument, where the predicate is a function that returns either true or false (.e.gisEven
). The predicate is applied to every value emitted by the source observable (.i.enumbers
), and only the values that match the predicate are re-emitted.obviouslyCorrectStatements
is an observable that emits a console-friendly representation ofevenNumbers
, where it transforms every even number into a string stating that the number is even. This is achieved by themap
operator, which is very similar toArray.map
, in that it takes a function that accepts value, and returns a different representation of that value (it maps every value to a new value). The passed function is then applied to every value emitted by the source observable (.i.e.evenNumbers
), and every transformed value is emitted.
Notice how we pass the operators to the pipe
method, which is essentially a way to chain operators to achieve the desired result. For example, this code is roughly equivalent to the code above:
The only difference being that we skipped creating the evenNumbers
observable, and went straight to having an observable of trivial statements about even numbers.
The pipe
method takes a list of operators, where every emitted value is passed to the first operator in the list, and the result of that operator is passed to the next operator, and so on.
A useful way of visualizing a pipe is as a literal pipe that data goes through:
There are many operators that can be immensely helpful, such as flatMap
, and reduce
, but we can’t cover them all in one post, so I recommend reading about them early on to save a huge amount of time. You can find example uses of each operator here.
Note: The only requirement a function needs to fulfill is to return an observable, which means that you can create your own operators.
Conclusion
RxJS is a great library that combines object-oriented and functional programming to strike a reactive balance between the two, and it does it elegantly. I think it’s a very useful tool for any JavaScript developer to master.
I hope you found this post useful. Have fun doing reactive programming!