How To Use ForkJoin — Angular Example
forkJoin
is a useful operator in Angular’s RxJS library for combining the results of multiple observables into a single observable. It waits for all the source observables to complete and then emits an array of the last values emitted by each source observable.
Here’s a real-world example of how forkJoin
can be used in an Angular app:
Let’s say we have an application that displays posts information, including the comments for a given post. We want to fetch this information from separate API endpoints and display it on a single page.
First, let’s define the interfaces for our post and comment data:
export interface Post {
id: number;
title: string;
body: string;
}
export interface Comment {
id: number;
postId: number;
name: string;
email: string;
body: string;
}
Next, we can create a service called PostService
that handles the API calls and returns observables for the post and comment data:
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
@Injectable()
export class PostService {
private apiUrl = 'https://jsonplaceholder.typicode.com';
constructor(private http: HttpClient) {}
getPost(postId: number): Observable<Post> {
const url = `${this.apiUrl}/posts/${postId}`;
return this.http.get<Post>(url);
}
getComments(postId: number): Observable<Comment[]> {
const url = `${this.apiUrl}/comments?postId=${postId}`;
return this.http.get<Comment[]>(url);
}
}
Now, in a component, let’s say PostDetailsComponent
, we can use forkJoin
to combine the post and comment observables:
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { forkJoin } from 'rxjs';
import { PostService } from './post.service';
import { Post, Comment } from './post.model';
@Component({
selector: 'app-post-details',
templateUrl: './post-details.component.html',
styleUrls: ['./post-details.component.css']
})
export class PostDetailsComponent implements OnInit {
post: Post;
comments: Comment[];
constructor(
private route: ActivatedRoute,
private postService: PostService
) {}
ngOnInit() {
const postId = +this.route.snapshot.paramMap.get('id');
forkJoin([
this.postService.getPost(postId),
this.postService.getComments(postId)
]).subscribe(([post, comments]) => {
this.post = post;
this.comments = comments;
});
}
}
In the example above:
- The
PostDetailsComponent
obtains the post ID from the route parameters using theActivatedRoute
service. - Inside the
ngOnInit
method, we useforkJoin
to combine the observables returned bygetPost
andgetComments
. - The combined observable emits an array containing the post and comment data once both API calls complete.
- We subscribe to the combined observable and assign the received data to the component properties (
post
andcomments
).
Finally, in the component’s template (post-details.component.html
), you can display the post and comment information:
<div *ngIf="post">
<h1>{{ post.title }}</h1>
<p>{{ post.body }}</p>
</div>
<div *ngIf="comments">
<h2>Comments</h2>
<ul>
<li *ngFor="let comment of comments">
<h3>{{ comment.name }}</h3>
<p>{{ comment.body }}</p>
</li>
</ul>
</div>
Make sure to import the necessary modules and provide the PostService
in your app’s module or component.
In this diagram:
- The
PostService
(A) provides methods to fetch post and comment data from the API. - The
getPost()
method fetches a single post (B) by ID. - The
getComments()
method fetches an array of comments © for a specific post ID. - The
forkJoin
operator (D) combines the observables returned bygetPost()
andgetComments()
. - The combined observable emits an array of the post and comment data.
- The
subscribe()
method receives the emitted data (E) and assigns it to thePost
andComments
variables in thePostDetailsComponent
.