How to use mergeMap and forkJoin to handle multiple API requests in Angular 🚀
Tags: webdev, tutorial, angular, typescript
Published: 2023-07-17 17:00:47

In this Article, I will explore the process of how to handle multiple API requests in Angular. Handling multiple API requests in Angular is a common scenario in modern web development. It's essential to implement an efficient and maintainable solution to avoid issues such as **nested subscriptions**. In this article, we will explore the proper way to handle multiple API requests using the _mergeMap_ and _forkJoin_ operators from the Angular RxJS library.

First of all, I will explain the problem.

## problem because we are not using nested subscriptions
In the real world, it is common to make multiple API calls in our web applications. When navigating to a page, it is often necessary to retrieve data from various APIs. In Angular, the subscribe operator is typically used to fetch data from a single API call. However, when dealing with multiple API calls, there are more effective methods to implement this. We can initially solve the problem using the **subscribe** operator and then improve upon it by utilizing **mergeMap** and **forkJoin**.

## Subscribe()
Normally, this technique is quite simple. However, when we trigger a new subscription for each and every value emitted by the Observable of **call()**, it can result in the creation of numerous unhandled Observables and Subscriptions. All of these entities remain in memory for the time being, leading to potential issues. Here is nested subscription example

```
export class DevToComponent implements OnInit {
    todoValue: string = '';
    comment: any;

    constructor(private http: HttpClient) { }

    ngOnInit(): void {

        this.retrieveDefaultData();
    }

    retrieveDefaultData(): void {
        this.http.get('https://jsonplaceholder.typicode.com/posts/1')
            .pipe(map(todo => todo[0]))
            .subscribe(
                todo => {
                    this.todoValue = todo;
                    this.http.get(`https://jsonplaceholder.typicode.com/posts/${this.todoValue}/comments`)
                        .subscribe(
                            coment => {
                                this.comment = coment;
                            }
                        );
                }
            )
    }

}
```
It's important to note that when you **subscribe()** to an Observable multiple times, your subscribers won't listen to the exact same source. Instead, each subscription triggers a new copy of the defined [Observable](https://rxjs-dev.firebaseapp.com/guide/observable) pipeline.


## MergeMap()
This operator takes an input observable, applies a transformation function to each emitted value, and merges the resulting observables into a single output observable.By using [MergeMap()](https://www.techgeeknext.com/angular/angular-rxjs-mergemap-operator), we can avoid nested subscriptions and achieve a more streamlined and efficient approach to handling asynchronous requests.

> We can use the MergeMap() when we need data information from first API request to second API request:

```
export class DevToComponent implements OnInit {
    todoValue: string = '';
    comment: any;
    mergeMapResult: any;
    constructor(private http: HttpClient) { }

    ngOnInit(): void {
        this.retrieveDefaultData();
    }

    retrieveDefaultData(): void {
        this.http.get('https://jsonplaceholder.typicode.com/posts/1')
            .pipe(
                map(todo => {
                    return todo
                }),
                mergeMap(todo => this.http.get(`https://jsonplaceholder.typicode.com/posts/${todo}/comments`))
            ).subscribe(response => {
                this.mergeMapResult = response;
            })
    }

}
```

Using mergeMap avoids nested subscriptions, you can avoid nested subscriptions and flatten the asynchronous operations. This leads to cleaner and more readable code, as the operations are executed sequentially instead of nesting multiple subscription callbacks.


## ForkJoin()
This operator,when you have multiple parallel API requests that are independent of each other and you want to wait for all of them to complete before taking further action, you can use the [forkJoin()](https://rxjs.dev/api/index/function/forkJoin) operator instead of nested subscriptions.

> We can use the ForkJoin() calling independent multiple API requests:

```
export class DevToComponent implements OnInit {
    todoValue: string = '';
    comment: any;
    firstApiResult: any;
    secondApiResult: any;
    constructor(private http: HttpClient) { }

    ngOnInit(): void {
        this.retrieveDefaultData();
    }

    retrieveDefaultData(): void {
        const firstAPI = this.http.get('https://jsonplaceholder.typicode.com/posts/1')
        const secondAPI = this.http.get(`https://jsonplaceholder.typicode.com/posts`)

        forkJoin([firstAPI, secondAPI]) //we can use more that 2 api request 
            .subscribe(
                result => {
                    //this will return list of array of the result
                    this.firstApiResult = result[0];
                    this.secondApiResult = result[1];
                }
            )
    }

}
```
Using forkJoin() simplifies the handling of parallel API requests by providing a clean and efficient way to wait for all requests to complete. It eliminates the need for nested subscriptions, improving code readability and maintainability.

> Note : Note that if any of the source observables in forkJoin() errors before completing, the entire observable will error and no result will be emitted. So, it's important to handle error cases appropriately when using forkJoin().

**Conclusion**
By adopting the use of mergeMap() and forkJoin() in RxJS, you have acquired a powerful technique for handling multiple API requests without resorting to nested subscriptions. This approach not only improves the readability and maintainability of your code but also allows for efficient parallel execution of asynchronous operations.

Thanks for reading the whole story ❤