Mandroid
Mandroid

Reputation: 7494

Angular with RxJs: Ensuring all observables are completed before

I have following code in angular using RxJs:

private loadData(id) {
    
        const inputData = .....

        this.backendservice.getData(inputData).pipe(take(1)).subscribe(data => {
            // do stuff
        });
        
}

Currently code deals with only a single id. Now I want to get it working for multiple ids, and have a possible code structure like:

private loadData(ids) {

        const Map myMap = new Map();
        for(let id of ids) {
           const inputData = .....
           this.backendservice.getData(inputData).pipe(take(1)).subscribe(data => {
               myMap.set(inputData, data)
               // do stuff
           });
        }
        // do more stuff with myMap
}

I want to process all the ids before 'do more stuff' part is executed. I update a map in the subscribe code and use it afterwards.What is best way to achieve this using RxJs in angular?

Upvotes: 0

Views: 187

Answers (2)

Mrk Sef
Mrk Sef

Reputation: 8022

Sounds like you want to want to forkJoin an array of streams, then take the result and transform it into a Map.

I've added in some console.log() statements that can act as debug points to help you better arrive at/understand your solution. The general shape it can take might look like this:

private loadData(ids): void {

  forkJoin(
    ids.map(id => {
      const inputData = ...;
      return this.backendservice.getData(inputData).pipe(
        take(1),
        map(data => ({id, inputData, data})),
        tap(result => console.log(`Service call ${result.id} complete`))
      );
    })
  ).pipe(
    tap(_ => console.log("All Service calls complete and output as an array")),
    map(resultArray => {
      const myMap = new Map();
      for(const result of resultArray){
        myMap.set(result.inputData, result.data);
        console.log(`Results from call ${result.id} added to Map`);
      }
      return myMap;
    }),
    tap(_ => console.log("Call resuls transformed into a Map data structure"))
  ).subscribe(myMap => {
    // Do more stuff with myMap
  });

}

Upvotes: 1

Aditya Menon
Aditya Menon

Reputation: 774

Use forkJoin like below:

private loadData(ids) {
        let observables=[];
        for(let id of ids) {
           const inputData = .....
           observables.push(
               this.backendservice.getData(inputData).pipe(take(1)).subscribe(data => {
                    // do stuff
                });
           )
        }
        forkJoin(observables).subscribe(res=>{
            // do more stuff
        })       
}

Upvotes: 0

Related Questions