Home > Net >  How can I call an API function in sequence for all of the elements of an array?
How can I call an API function in sequence for all of the elements of an array?

Time:10-15

I am working with Angular using RxJs, and currently find it very challenging to solve this problem.

I have an array which contains some ids.

ids = [1,2,3,4]

Then I have an API that can be called with the id param, which deletes the item with the given id from the database:

this.controller.deleteItem(id)

I want to call this API on every id in the array.

These API calls should strictly happen one after another in a sequential pattern, like

this.controller.deleteItem(1) -> this.controller.deleteItem(2) etc.

After all of the api calls finished, I would like to fetch the data with:

this.controller.getData()

How can I solve this?

CodePudding user response:

You can do it using the concat operator.

First you need to turn the list of IDs into a list of observables, by mapping each item of the array into its corresponding delete action:

const idsToDelete = [1, 2, 3];
const deleteTasks = idsToDelete.map(id => this.controller.deleteItem(id));

Then use concat to execute the tasks sequentially:

concat(...deleteTasks).subscribe((response) => {
  console.log('deleted', response);
});

For getting the data at the end, (assuming that the getData method also returns an observable) you can insert it at the end, after the deletes, and only listen for the last response:

concat(...deleteTasks, this.controller.getData()).pipe(
  // tap((res) => console.log(res)),
  last()
).subscribe((dataAfterDelete) => {
  console.log(dataAfterDelete);
});

You can also split these calls if you want to get the chance to perform side effects between the delete operations and the data fetch by using the switchMap operator:

const sequentialDelete = concat(...deleteTasks);
sequentialDelete.pipe(
  tap((deleteItemResponse) => {
    console.log('after each item delete', deleteItemResponse);
  }),
  last(),
  tap(() => {
    console.log('after the last item was deleted');
    this.idsToDelete = [];
  }),
  switchMap(() => this.controller.getData())
).subscribe((dataAfterDelete) => {
  console.log(dataAfterDelete);
});

CodePudding user response:

In simple RxJS way (assumed that both controller functions returns Observables)

concat(
 from(ids).pipe(concatMap(id=> this.controller.deleteItem(id))),
 this.controller.getData()
)

CodePudding user response:

NOTE: NOT SEQUENTIAL

forkJoin(
  ids.map<Observable<number>>((id: number) => 
    this.controller.deleteItem(id) )
).subscribe(val => this.controller.getData())

forkJoin

When all observables complete, emit the last emitted value from each.

map your ids array into an Observables array using your "this.controller.deleteItem(id)" then pass that array to forkJoin and subscribe to it. forkJoin does all the deleteItem calls at the same time and emits the output of each when all complete. When all succeed you can call getData()

CodePudding user response:

ids.forEach(async (id) => {
  await this.controller.deleteItem(id);
};

Will call your api sequentially.

  • Related