Search code examples
angulartypescriptpromiserxjsobservable

Loop with http get request returns scrambled data Angular


I have a loop, in which there is a http GET request.

Loop code:

for (let index = 0; index < datas.length; index++) {
   let car = datas[index].smiles;
   console.log('or--> ' + car);
    this.subscr = this.CarService.getCarForm(car).subscribe((val) => {
     console.log(val);
     });
 }

The GET request is a service:

public getCarForm(car: string) {
   return this.http.get(this.url_conn + this.encode(car), {
    responseType: 'text',
  });
 }

The result of the loop is: "1", "3", "5", "4", "2"

Instead of: "1", "2", "3", "4', "5'

I am using:

  • rxjs: 7.8.0
  • angular/cli: 15.1.6

I have tried using pipe(first()), unsubscribing(), separate the GET request in new function; using a Promise instead of Observable. The result is always the same.


Solution

  • there could be a couple of reasons for this behavior, the reason could be in the backend api if you are indexing the response by some parameter sent from the front end, if not then try these methods.

    observables initiate calls even if the last call response arrived or not they initiate another call and return responses as they arrive, so there is no sequence of which will come when. and even if you use a promise you need to make the loop pause until the response, which is hectic. like you would need to take the service call in a separate function wrap it in a promise that resolves on response from the observable subscription.

    Or you can use the rxjs operator switch map. make an observable and loop the call as next and add a switch map on the observable you make. or you can use forkjoin. forkjoin takes an array and will wait for all calls in the array to complete and send response then it will emit values/responses in the same order the calls were made in the array.

    check the link below it shows a synced loop calls behavior using observables and switchmap() operator or ForkJoin.

    switchmap operator: https://www.tektutorialshub.com/angular/using-switchmap-in-angular/

    forkJoin operator: https://medium.com/@swarnakishore/performing-multiple-http-requests-in-angular-4-5-with-forkjoin-74f3ac166d61

    async loopCallsFunction () {
      //callResponses = [];
      for (let index = 0; index < datas.length; index++) {
       let car = datas[index].smiles;
       await this.syncCalls(car).then(res=> console.log(res) );
       //or you can add each response in an array
       //await this.syncCalls(car).then(res=> callResponses.push(res) );
      }
     }
     
     syncCalls (car) {
      return new Promise((reject,resolve)=>{
          this.subscr = this.CarService.getCarForm(car).subscribe((val) => {
              if (val) {
                resolve(val);
              } else {
                reject();
              }
            },(error)=>{
                reject(error); 
              });
        });
     }