Making multiple HTTP requests and combining their responses is a common requirement in modern Angular applications. Whether you're fetching user profiles, loading dashboard data, or aggregating analytics from multiple endpoints, you need a way to manage concurrent HTTP calls cleanly and efficiently.
In this updated tutorial, you’ll learn how to use RxJS forkJoin
with the latest Angular 20 using standalone components—no NgModules required. We'll walk through setting up your app, creating a service that fetches data from multiple APIs, and handling combined responses in a clean, reactive way using the HttpClient
.
Setup (Angular 20, RxJS 7+)
We will create an Angular 20 application using Angular CLI from the terminal or command line. For that, we have to install a new @angular/cli or update an existing @angular/cli using this command from the terminal or command line.
sudo npm install -g @angular/cli
You can skip `sudo` if you are using the Command-Line or if your terminal allows it without `sudo`. To check the existing version of Angular CLI, type this command.
ng version
We are using Angular and RxJS versions. Next, we have to create a new Angular application using this command.
ng new angular-forkjoin
Answer the question the same as below.
? Would you like to add Angular routing? No
? Which stylesheet format would you like to use? SCSS [ https://sass-lang.com/documentation/synta
x#scss
Next, go to the newly created Angular application folder, then run the Angular application for the first time.
cd ./angular-forkjoin
ng serve
Now, open the browser, then go to `http://localhost;4200/` and you will see the standard Angular page.
Service: Combining Multiple HTTP Calls
The Angular `HttpClient` module should be registered in the Angular main module. Update src/app/app.config.ts:
import { ApplicationConfig, provideBrowserGlobalErrorListeners, provideZoneChangeDetection } from '@angular/core';
import { provideRouter } from '@angular/router';
import { routes } from './app.routes';
import { provideHttpClient } from '@angular/common/http';
export const appConfig: ApplicationConfig = {
providers: [
provideBrowserGlobalErrorListeners(),
provideZoneChangeDetection({ eventCoalescing: true }),
provideRouter(routes),
provideHttpClient(),
]
};
The main feature that we mention in the title of this tutorial is using the RxJS forkJoin to call multiple RESTful API in one call. We do that in the Angular Service. For that, generate a new Angular service using Angular CLI.
ng g service rest-api.service
Next, open and edit `src/app/rest-api.service.ts` then add these imports of Observable, of, throwError (rxjs), HttpClient, HttpHeaders, HttpErrorResponse (@angular/common/http), forkJoin (rxjs).
import { Observable, of, throwError } from 'rxjs';
import { HttpClient, HttpHeaders, HttpErrorResponse } from '@angular/common/http';
import { forkJoin } from 'rxjs';
Add this line after the import lines as a constant variable of the RESTful API endpoint that we will use.
const apiUrl = 'http://localhost:1337/www.metaweather.com/api/location/';
As you see, we are using the `localhost:1337` in front of the Meta weather URL because the RESTful API, not CORS enabled. For that, we have to install the Corsproxy-HTTPS using this command.
sudo npm install -g corsproxy-https
Next, inject the `HttpClient` module into the constructor.
constructor(private http: HttpClient) { }
Next, create multiple RESTful API calls at once in a function using the above API URL with a different parameter value that describes the code of the city.
getData(): Observable<any> {
const response1 = this.http.get(apiUrl + '44418/');
const response2 = this.http.get(apiUrl + '2459115/');
const response3 = this.http.get(apiUrl + '28743736/');
const response4 = this.http.get(apiUrl + '1940345/');
return forkJoin([response1, response2, response3, response4]);
}
As you see, the forkJoin combines the 4 API calls at the end of the function.
Note: Using
forkJoin({ … })
returns a named object, preserving request order with keys instead of an array.
Component: Displaying Aggregated Results
Now, we have to display the 4 different API calls' responses to the Angular page using Angular Material. First, we have to add Angular Material using the Angular CLI.
ng add @angular/material
Answer all questions that appear during the installation as below.
? Choose a prebuilt theme name, or "custom" for a custom theme: Indigo/Pink [ Preview: https
://material.angular.io?theme=indigo-pink ]
? Set up HammerJS for gesture recognition? Yes
? Set up browser animations for Angular Material? Yes
Next, open and edit `src/app/app.ts`, then add this import.
import { Component } from '@angular/core';
import { RestApiService } from './rest-api.service';
import { CommonModule } from '@angular/common';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MatCardModule } from '@angular/material/card';
Add these to the component imports.
@Component({
selector: 'app-root',
imports: [
CommonModule,
MatProgressSpinnerModule,
MatCardModule
],
templateUrl: './app.html',
styleUrl: './app.scss'
})
Add these lines of variables after the title variable.
data1: any = {};
data2: any = {};
data3: any = {};
data4: any = {};
isLoadingResults = true;
error?: string;
Add the constructor that injects the REST API service and call the get data function.
constructor(private api: RestApiService) {
this.getData();
}
Add a function to get data from the REST API service.
getData() {
this.api.getData()
.subscribe({
next: (res) => {
console.log(res);
this.data1 = res[0];
this.data2 = res[1];
this.data3 = res[2];
this.data4 = res[3];
this.isLoadingResults = false;
},
error: (err) => (this.error = 'Failed to load data')
});
}
Next, open and edit `src/app/app.html`, then replace all existing HTML tags with these tags.
<div class="example-container mat-elevation-z8">
<div class="example-loading-shade"
*ngIf="isLoadingResults">
<mat-spinner *ngIf="isLoadingResults"></mat-spinner>
</div>
<mat-card class="example-card">
<mat-card-header>
<mat-card-title><h2>{{data1.title}}</h2></mat-card-title>
<mat-card-subtitle>Sunrise at {{data1.sun_rise | date: 'HH:mm:ss'}}, Sunset at {{data1.sun_set | date: 'HH:mm:ss'}}</mat-card-subtitle>
</mat-card-header>
<mat-card-content>
<ul>
<li *ngFor="let source of data1.sources"><a href="{{source.url}}" target="_blank">{{source.title}}</a></li>
</ul>
</mat-card-content>
</mat-card>
<mat-card class="example-card">
<mat-card-header>
<mat-card-title><h2>{{data2.title}}</h2></mat-card-title>
<mat-card-subtitle>Sunrise at {{data2.sun_rise | date: 'HH:mm:ss'}}, Sunset at {{data2.sun_set | date: 'HH:mm:ss'}}</mat-card-subtitle>
</mat-card-header>
<mat-card-content>
<ul>
<li *ngFor="let source of data2.sources"><a href="{{source.url}}" target="_blank">{{source.title}}</a></li>
</ul>
</mat-card-content>
</mat-card>
<mat-card class="example-card">
<mat-card-header>
<mat-card-title><h2>{{data3.title}}</h2></mat-card-title>
<mat-card-subtitle>Sunrise at {{data3.sun_rise | date: 'HH:mm:ss'}}, Sunset at {{data3.sun_set | date: 'HH:mm:ss'}}</mat-card-subtitle>
</mat-card-header>
<mat-card-content>
<ul>
<li *ngFor="let source of data3.sources"><a href="{{source.url}}" target="_blank">{{source.title}}</a></li>
</ul>
</mat-card-content>
</mat-card>
<mat-card class="example-card">
<mat-card-header>
<mat-card-title><h2>{{data4.title}}</h2></mat-card-title>
<mat-card-subtitle>Sunrise at {{data4.sun_rise | date: 'HH:mm:ss'}}, Sunset at {{data4.sun_set | date: 'HH:mm:ss'}}</mat-card-subtitle>
</mat-card-header>
<mat-card-content>
<ul>
<li *ngFor="let source of data4.sources"><a href="{{source.url}}" target="_blank">{{source.title}}</a></li>
</ul>
</mat-card-content>
</mat-card>
</div>
Finally, open and edit `src/app/app.scss`, then add these lines of SCSS code to make an adjustment for the styles.
.example-container {
position: relative;
padding: 5px;
background-color: aqua;
}
.example-loading-shade {
position: absolute;
top: 0;
left: 0;
bottom: 56px;
right: 0;
background: rgba(0, 0, 0, 0.15);
z-index: 1;
display: flex;
align-items: center;
justify-content: center;
}
.example-card {
margin: 5px;
padding-bottom: 40px;
}
Handling Conditional or Nested Requests
If you need to make additional calls based on previous results, combine forkJoin
with mergeMap
or switchMap
. Example:
import { forkJoin, mergeMap, Observable } from 'rxjs';
getDataWithDetails(): Observable<any> {
return this.http
.get<{ id: string }[]>(`${apiUrl}list`)
.pipe(
mergeMap((items) => {
const detailCalls = items.map(item =>
this.http.get(`${apiUrl}details/${item.id}`)
);
return forkJoin(detailCalls);
})
);
}
Key RxJS Tips in Angular 20
-
Use named keys when calling
forkJoin({ … })
—results will match the keys, eliminating array-index errors learnrxjs.io+3coryrylan.com+3stackoverflow.com+3stackoverflow.com+1coryrylan.com+1. -
Understand that
forkJoin
emits only when all Observables complete, and will error loudly if any source fails djamware.com+14learnrxjs.io+14sparkcodehub.com+14. -
For partial success, handle errors with
catchError
inside each observable.
Run and Test the Complete Angular RxJS Example
As you see in the previous steps, we have already installed the Corsproxy-HTTPS Node module. So, open the new Terminal/Command Line tab, then run the Corsproxy before running the Angular Application.
corsproxy
Back to the current Terminal tab, type this command to run the Angular application.
ng serve
In the browser, go to `http://localhost:4200/`, then you will see a single page like below.
Conclusion
Angular 20 and RxJS 7+ provide a powerful and concise way to handle multiple HTTP requests using forkJoin
. With standalone components and modern reactive patterns, your code is cleaner, modular, and easier to maintain.
Key benefits of using forkJoin
in Angular:
-
Combine parallel HTTP requests and wait for all to complete
-
Use named keys for clear and predictable responses
-
Simplify UI logic by handling all results in one place
By applying these modern Angular features, you’ll write less boilerplate and build more scalable frontend code. Don’t forget to explore other RxJS operators like combineLatest
, switchMap
, or mergeMap
for handling more dynamic or conditional workflows.
That's the Angular RxJS Multiple HTTP Request using the forkJoin Example. You can find the full source code on our GitHub.
If you don’t want to waste your time designing your front-end or your budget to spend by hiring a web designer, then Angular Templates is the best place to go. So, speed up your front-end web development with premium Angular templates. Choose your template for your front-end project here.
That's just the basics. If you need more deep learning about MEAN Stack, Angular, and Node.js, you can take the following cheap course:
- Master en JavaScript: Aprender JS, jQuery, Angular 8, NodeJS
- Angular 8 - Complete Essential Guide
- Learn Angular 8 by creating a simple full-stack web App
- Angular 5 Bootcamp FastTrack
- Angular 6 - Soft & Sweet
- Angular 6 with TypeScript
Thanks!