RxJS concatMap (2020)
RxJS Tutorial - Table of Contents
In previous article we have seen RxJS Higher-Order Observable Mapping Now let understand RxJS Observable Concatenation in this article
At this point, you should have a fair understanding of the basics about observable, observers and subscriptions.
Now to incorporate sequential HTTP requests, we will introduce a new concept of Observable Concatenation. In this code example, we concatenate two observable examples using the concat() RxJs function
const series1$ = of('a', 'b'); const series2$ = of('x', 'y'); const result$ = concat(series1$, series2$); result$.subscribe(console.log);
Here is the output console of this program, showing the values emitted by the Observable result:
a b x y
As we can see, the values come from the combination of series1 $with series2$. But here's the catch: it works only because the Observables are completed!!
Observable Concatenation Marble Diagram
For understand what is happening, we must see the marble diagram of observable concatenation.
Let's break down what is happening here step by step with the timeline:
- First the two Observables series1$ and series2$ are passed to the concat() function
- concat() will then subscribe to the first Observable series1$
- note that the source2$ Observable is not yet subscribed so not emitting values.
- source1$ emits the first value a, which gets immediately reflected in the output result$ Observable
- source1$ will then emit the second value b, which gets reflected in the output
- source1$ will then complete
- Now after completion of source1$, concat() now subscribe to source2$
- the source2$ values will then start emitting values and getting reflected in the output, until source2$ completes
- when source2$ completes, then the result$ Observable will also complete
we can pass as many Observables as we want to concat() and the it will subscribe then one by one
So the key point about Observable Concatenation, Observable concatenation is all about Observable completion! We take the first Observable and use its values, wait for it to complete and then we use the next Observable, etc. until all Observables complete.
Using Observable Concatenation to implement sequential request
Going back to our higher-order Observable mapping example, RxJS Higher-Order Observable Mapping
To ensure sequentiality in higher-order Observable, we need to combine multiple httpPost$ Observables!
It is the RxJs concatMap Operator, which will help this higher-order mapping mixture of Observable concatenation that we need.
RxJs concatMap Operator
Here is the sample code looks like if we now use the concatMap Operator:
Benefit with concatMap :
this.form.valueChanges .pipe( concatMap(formValue => this.http.put("/api/book/",formValue)) ) .subscribe( response => ... handle successful ..., err => ... handle error ... );
- We no longer have to use nested subscribes with higher-order mapping operator
- All http request are sent to the backend sequentially
This is how the operator concatMap ensures that the requests still occur in sequence:
- concatMap takes each form value and transforms it into an observer HTTP, known as an inner observer.
- concatMap subscribes to the inner Observable and sends its output to the Observable result
- The second form value can come more quickly than is needed to request in the backend the previous form value. When this occurs, the new form value is not converted to an HTTP request immediately.
- ConcatMap is waiting for previous HTTP Observable to complete in and then trigger a next request, before mapping the new value to an HTTP Observable.
Notice that the code here is just the basis of an implementation on form values changes. You can combine this with other operators like debounce and others to make sure that they don't occur too frequently.
Next we will see mergeMap