Sergio Cea
Sergio Cea

Reputation: 13

Question about managing Observables in Angular 14

I'm new to Angular and right now I'm using Angular 14 and I have a problem that happens to me often.

For example, I have an array and I make a for loop to go through each of its indexes and I make a POST call. The call and the functionality of the call are in a service and there I manage the result.

The problem I encounter is when below that for I have another http call that has to be executed when all the for calls have finished.

How can I perform this task?

for (let entrie of entries) {
   this.service.callPost(entrie);
}

// Only when all the for calls have finished
this.service.callFinal();

I have seen that one option is to use forkJoin and store each call in an observable array and execute the final function within the forkJoin.

Thank you very much for the help.

I want to perform this type of operation since I perform an update of several data (for calls) and when these finish based on whether one gave an error or not the final call updates in one way or another, but the problem is that being asynchronous the final call does not wait for the for calls to finish.

Upvotes: 1

Views: 66

Answers (2)

Raphaël
Raphaël

Reputation: 3751

You can use forkJoin and switchMap for that:

import { forkJoin } from 'rxjs';
import { switchMap, catchError } from 'rxjs/operators';

let entries: string[];

// Fork join will wait for every given observable to finish before calling next.
const observable = forkJoin(
  entries.map(entry => this.service.callPost(entry))
).pipe(
  // switchMap will switch to an other Observable when forkJoin completes.
  switchMap(results => this.service.callFinal().pipe(
    catchError(error => {
      // Handle the error
    })
  ))
);

This will create an observable that will send a POST call for every entry of the entries array and that will call final afterward.

Note that you need to subscribe to this observable to start the process, either by calling it directly or by using the async pipe.

observable.subscribe({
  next: () => {
    // Success!
  },
  error: reason => {
    // Tell the user something went wrong.
  }
});

Upvotes: 0

Thomas Renger
Thomas Renger

Reputation: 1104

It depends on your service code

Lets say you callPost ist returning a promise then add await to you code

for (let entrie of entries) {
   await this.service.callPost(entrie);
}

// Only when all the for calls have finished
await this.service.callFinal();

Lets say you are returning the observable

for (let entrie of entries) {
   await lastValueFrom(this.service.callPost(entrie));
}

// Only when all the for calls have finished
await lastValueFrom(this.service.callFinal());

Please notice in this case no subscribe is needed and i guess this is your problem. you cannot await the subscribe. In this case you needed to transform the observable to promise as written above.

This is something you should already to in the service.

Upvotes: 0

Related Questions