Chaining HTTP Calls Using Observables With RxJS
photo from Wikipedia

Chaining HTTP Calls Using Observables With RxJS

Sometimes we need to make multiple HTTP calls in a specific order to get data. The data from previous call are either required as the input for the next call or they just must be in that logic order to make sense. In the following code examples we use RxJS of operator to create Observables to mock HTTP calls.

Nested Subscriptions

The first solution we can come up with is to use nested subscription. The code below has a few disadvantages. The code is a bit difficult to read obviously and thus will be hard to maintain. Also, even those Observables will be started in the order of first, second and third. The order of complete is in the reverse order. The log output will be like:

import { delay, of} from 'rxjs';
 
let first$ = of(1).pipe(delay(100));
let second$ = of(2);
let third$ = of(3);
 
first$.subscribe(
	data => {
		console.log("First data returned");
		second$.subscribe(
			data => {
				console.log("Second data returned");
				third$.subscribe(
					data => {console.log("Third data returned")},
					error => {},
					() => { console.log("Third call completed")}
				)},
			error => {},
			() => { console.log("Second call completed")}
		)	
	},
	error => {},
	() => { console.log("First call completed")}
);        

The log output:

First data returned 
Second data returned
Third data returned
Third call completed
Second call completed
First call completed        

Use concatWith

RxJS concatWith (concat works as well) operator let us use a source Observable and multiple other Observables for chaining after source Observable completed. Each of provided Observable won't be subscribed until the one before it completes.

import { concatWith, delay, of} from 'rxjs';
 
let first$ = of(1).pipe(delay(100));
let second$ = of(2).pipe(delay(100));
let third$ = of(3);

first$.pipe(concatWith(second$, third$))
  .subscribe(
	data => console.log(data)
 );        

We add a delay to the first two Observables but the third one won't complete before the first two. The log from above code will be 1, 2 and 3. This solution is simple but has one drawback: it doesn't allow subscription to individual Observable which is sometimes not desirable.

Use switchMap to set loosely chained calls

RxJS switchMap operator allow us to map source values to Observables as output.

import { of, switchMap} from 'rxjs'

let obsA$ = of("first call A");
let obsB$ = of("second call B");
let obsC$ = of("third call C");

obsA$.subscribe(
	data => console.log(data),
	error => {},
	() => console.log("A completed")
  );

obsA$.pipe(	switchMap(() => obsB$))
  .subscribe(
	data => console.log(data),
	error => {},
	() => console.log("B completed")
 );
 
obsB$.pipe(switchMap(() => obsC$))
  .subscribe(
	data => console.log(data),
	error => {},
	() => console.log("C completed")
 );        

In the code above, Observables obsA$, obsB$ and obsC$ will be called and completes in the order of A, B and C due to the fact that the next Observable only get subscribed when previous one completes. The log output:

first call A
A completed
second call B
B completed
third call C
C completed        

Although the code is longer than concatWith solution, the code is very flexible and readable. This solution is way better than the nested subscriptions regarding maintenance.



To view or add a comment, sign in

More articles by Lixin C.

  • Solution Architect - part 1

    Solution Architects (SA) are responsible for providing solutions to fulfill business requirements by working with…

  • Retrieve Data From Multiple Microservices

    In microservice pattern, microservices are suppose to own their own database to achieve best independent scalability…

  • RxJS Concise Demo - Creation Operators

    RxJS operators are functions that can create or process Observables. Creation operators are used to create new…

  • Async Controller Methods For Scalability

    In API action methods, it is very common to call a database or another web resource to get requested data. Getting data…

  • Angular Component Lifecycle Hooks

    Angular lifecycle hooks allows you to implement critical logic at the right time of a component's lifecycle. During the…

  • HTTP Status Code Short listed

    Commonly Used HTTP Status Codes for Web Services. 200 => OK, general indication of request success.

  • Network Layers for Software Engineers

    Sending messages to another person using web browser or mobile app is not surprisingly easy nowadays and most people…

  • Implementing a Fixed-Window Median Data Stream With Heaps

    A data stream is like a pipe with moving data inside. Here I only consider integer numbers as data and try to find the…

  • Test Your Testing Strategy with A Dice Game

    1. Project background Sometime in last year I got interested in how does the 3D web rendering engines work.

Others also viewed

Explore content categories