Radiant
Radiant

Reputation: 390

Weird behaviour of for loop

I have array of products with their article numbers.

0:"3323"
1:"3319"
2:"3322"
3:"3331"
4:"3309"
5:"3317"
6:"3316"
7:"3329"
8:"3330"
9:"3332"
10:"3324"

I am passing every aticle number of this array to service to get details of respective product to show image. When I push image propery of each product in array, everytime I am getting different value at every index.

I want to have every article's image on the same index like the above array. Example : 3323's image at 0th index in new array.

werbedata: WerbeData[];
produkt: Produkt[];
urls: string[] = [];

  getWerbeData(filialewerbenr) {
    this.werbedataService.getWerbeData(filialewerbenr)
      .then(
        (werbedata) => {
          this.werbedata = werbedata[0];
          this.anums = this.werbedata.ArtNr.split(' ');
          console.log(this.anums);
          for (let i = 1; i < this.anums.length; i++) {
            let articleNumber = this.anums[i];
            this.produktService.getProdukt(articleNumber)
              .then(
                (product) => {
                  this.produkt = product[0];
                  this.urls.push(this.produkt.PfadBild_1);
                }
              );
          }
        },
    )
  }

Where I am doing mistake so that I will get respective products detail at respective index?

Upvotes: 0

Views: 73

Answers (2)

Thijs
Thijs

Reputation: 2351

You can keep track of all the promises and wait for all of them to be done. The snippet below shows how you may do this.

const
  productNumbers = ["3323","3319","3322","3331","3309","3317","3316","3329","3330","3332","3324"];
  
function getWerbeData(id) {
  // Do your webservice call and make sure it returns a promise. This code 
  // will wait between 500ms and 1000ms before returning a fake result.
  console.log(`[${id}] - getting data`);
  return new Promise(resolve => {
    setTimeout(() => {
      console.log(`[${id}] - data received`);
      resolve(`result for ${id}`)
    }, (Math.random() * 500) + 500);
  });
}

const
  // Creates a new array with for each product number a promise.
  promises = productNumbers.map(productNumber => getWerbeData(productNumber));
  
// Wait for all the promises to be resolved and print a log line.
Promise.all(promises)
  .then(() => console.log('all data retrieved'));

Upvotes: 0

JanRecker
JanRecker

Reputation: 1847

an Array starts with index 0. Your for-loop starts wit i = 1. Therefor you allways get the following item and not the one you have expected.

=> for (let i = 0; i < this.anums.length; i++) {

warm regards

UPDATE: My mistake. You are iterating over the array (synchronously), but then you do an async-call to get additional data. There is no guaranty, that the first called async call will also be the first one that finishs.

So, the order at the end depends heavily on this async-Call

 this.produktService.getProdukt(articleNumber)

UPDATE 2: The solution would be to build a result structure. There you have to deliver all results of your async .getProduct call in the right order. Then you have to check if all async calls have finished... And after that you can iterate over the result structure and get your data in the correct order.

It´s a while that i worked with promises (i realy love rxjs :-) ) Therefore there may appear problems with transfering the index-information and the counter into the .then Method...

let resultData = [];
let counter = 0;
for (let i = 1; i < this.anums.length; i++) {
        let articleNumber = this.anums[i];
        counter++;
        this.produktService.getProdukt(articleNumber)
          .then(
            (product) => {
              this.produkt = product[0];
              resultData[i] = this.produkt.PfadBild_1;
              counter--;
            }
          );
      }
      // Now wait until counter reaches again 0, than your result structure should be up to date.

Upvotes: 1

Related Questions