RXJS - forkJoin Operator

The forkJoin operator accepts a multiple number of input observables and waits for the completion of every passed observable(s). It will then emit a collection of the final values from the observables once they are completed in the same order as passed.

It can take an array or an object as input parameter.

Example

import { forkJoin, of, timer } from 'rxjs';
 
const observable = forkJoin({
  foo: of(3, 2, 1, 3),
  bar: Promise.resolve(true),
  baz: timer(4000)
});
observable.subscribe({
 next: value => console.log(value),
 complete: () => console.log('This is how it ends!'),
});

Output

{foo: 3, bar: true, baz: 0}
This is how it ends!

In the above example, an object is passed as an input to the forkJoin. Each property of the object has an Observable as its value.
Here, once all the observables are completed, it will return the value. In this case, the output is printed to the console after 4 seconds.

Let us see another example that makes 2 api calls in parallel and responds finally which will be handled and displayed in component template with async pipe.

Create a component named UserComponent and add the following code.

import { Component, Injector, OnInit } from '@angular/core';
import { combineLatest, forkJoin, map, of, timer } from 'rxjs';
import {HttpService} from '../services/http.service';

@Component({
  selector: 'app-user',
  templateUrl: './user.component.html',
  styleUrls: ['./user.component.scss']
})

export class UserComponent implements OnInit {

  vm$= forkJoin({
    users:this.getUsers(),
    avator:this.getAvatar()
  })
  .pipe(
    map((response:{users:any, avator:any})=>{
      // Do some processing if needed.
      return response;
    })
  );
  
  constructor(private httpService:HttpService) { 
  }

  ngOnInit() {
  }

  getAvatar():Observable<any>{
    return this.httpService.get(`https://api.sampleapis.com/avatar/info`);
  }

  getUsers():Observable<any>{
    return this.httpService.get('https://reqres.in/api/users?page=2').pipe(
      map((data:any)=>{
        return data.data;
      })
    );
  }
}

The above code contains two functions, getAvator() and getUsers() function. Both the function make api call and returns an Observable as response.

Then we pass an object with two property users and avator with getAvator() and getUsers() function as value.

Open the template of the component and add the following code.

<div>
    <ng-container *ngIf="vm$ | async as response">
        <h1>List of Users</h1>
        <hr/>
        <ng-container *ngFor="let user of response.users">
            <ul>
                    <li>{{user.first_name}}</li>
            </ul>
        </ng-container>
        <h1>List of Directors</h1>
        <hr/>
        <ng-container *ngFor="let avator of response.avator">
            <ul>
                <li>
                    <p>{{avator.creators[0].name}}</p>
                </li>    
            </ul>
        </ng-container>
    </ng-container>
</div>

Next, using the async pipe we subscribe to its value and render the contents once the response is available.

If you want to make multiple requests when a page loads, and act only
when all of the requests have returned the response. The API calls are
made in parallel by forkJoin.

If any of the inner observables supplied to forkJoin fail, you will
lose the value of any other observables that have been already
completed.


Most Read