DEV Community


Posted on

Reactive Patterns with rxjs


This is to describe different ways for components to handle to changes in data and render that data to the screen.

What is rxjs?

rxjs is the Javascript library to implement the reactive pattern. This is the pattern of processing event streams that are sent (or published) to your application. This pattern is also called the sub / pub pattern where there is a subscriber (your application) and a publisher (the source of the data that is being published). The publisher can be in the form of a socket that your application listens to, a timer that sends data on an interval, an http request, events occurring within the application, etc.

How it is implemented

rxjs uses operators to process data. The types of operators are:

Creation operator:

This creates an observable that your application can subscribe to. An observable listens for an event to be published and anything that subscribes to that instance of that observable can perform logic to process the new data to update the application.

Examples of this type of operators are:

merge: This takes 2 or more observables and creates one observable.

from: This creates an observable from a value. This is commonly used for creating an observable from a promise. Note: This processes incoming data one by one. For example, if you try to create an observable from a string, an event for every character in the string will be sent into the "pipe" and the output will only be the last character of the string unless during the processing, you concat each character to the previous character.

of: This creates an observable from a value as well. The difference is that it processes the value all at once so in the example with the string, you do not need to concat the characters as you will only have one event that is published, which would contain the entire string value.

fromEvent: This creates an observable from native HTML element events. The parameter to create the observable is the HTML element and the event that will trigger an event / data to be processed.

combineLatest: This takes 2 or more observables and creates a callable parameter that is passed for processing. See example described below:

Alt Text

Pipeable operator:

This operator takes an event generated from a creation operator, transforms it to a data structure that can be processed by a higher order operator or another pipeable operator. The most common operator is map.

The difference between a pipeable operator is that in a pipeable operator, the data returned is an observable that is can be consumed by the next operator. In a higher order operator, the returned data must be converted into an observable if it is to be consumed by another pipeable or higher order operator.

Higher Order operator:

This operator can take the event streams as they come in and make transformations to its data structure and output a new value that can then be used by as an input to other pipeable or higher order operators. These type operators are are sometimes called inner observables where the processing takes place on the inner observable and outputs the value to the outer observable, letting that data go to the next step of the processing.

switchMap: This processes the streams that come in and outputs a value. With this operator, if a new stream comes into the “pipe” (the inner observable), it will stop processing the old stream and replace it with the new stream to perform the processing and pass it back to the outer observable.

mergeMap: This processes the streams and outputs a value. With this operator, if a new stream comes into the “pipe”, it will merge it with the previous stream by creating a new inner observable. After the first inner observable finishes, it will process the next observable in the queue. The main point here is that order does NOT matter.

concatMap: This process the stream and output a value. With this operator, if a new stream comes into the “pipe”, it will concatenate it with the previous stream. The main point here is that order DOES matter. We will not create a new inner observable here. We will process stream 1 and once that finishes, we will process stream 2 and the data from processing stream 2 is what will pass to the outer observable to go through the next “pipe”.

Take the following scenario:
We have an event that we subscribe to that is triggered 3 times within the application. When event 1 is triggered, then event 2, then event 3. None of the events finish processing before any of the other events can finish and be sent to the next operation. The order in which they finish processing is event 2 first, then event 3, then event 1. The final data output to the next operation would be as follows.

switchMap and concatMap: The will output event 3. The difference is that switchMap will stop processing the event as a new event comes in. So if event 2 has logic and event 3 comes in, the logic to be performed after event 3 comes in will NOT be performed. If concatMap is used, all the logic from event 1 will happen, then event 2, then event 3 and finally event 3 will be processed and output to the next observable.
mergeMap: This will output event 1. The difference between mergeMap and concatMap is that with mergeMap the processing time within the inner observable matters. With concatMap, the order in which the events came into the "pipe" is what matters. With mergeMap, it will process event 1, and when event 2 comes in, it will create a new inner observable and start process the observable once event 1 is finished. So since event 1 finishes last, that is what will be output. With concatMap, it will fully finish the events in the order they come in, thus processing event 1, then 2, and finally outputting 3.

Why Should I Use rxjs?

One of the main benefits of using rxjs is that it follows the idea of functional programming. We should not mutate the application that calls the events to be processed. The data is mutated within the streams then output to the application to be consumed. This makes state management and testing your application easier. Note: If you need to mutate the application within the while processing data is occurring, it is you should use the tap operator to do so..

Top comments (0)