-1

I am struggling with asynchronous loop, here is what I tried:

let array = [];      
  raw.forEach(async element => {
      var elt = new Elt(raw);
      elt.options = await this.getOptions(raw["id"]);
      array.push(elt);
  });
  return array; // this is empty...

How can I "wait for it to be finished" so that the array isn't empty? Thanks a lot!

Maxiss
  • 986
  • 1
  • 16
  • 35

3 Answers3

3

Your first problem: The output array is empty because you use it before any of promises is executes. You have to await all promises before using the array.

The second problem: Promises can execute and therefore push items in (pseudo-)random order. Your output array can get shuffled.

The solution is (1) await all promises and (2) keep order of them (using Array.prototype.map):

async function foo(input) {
    let output = await Promise.all(input.map(async element => {
        return element * 2;
    }));

    return output;
}

// Call it
let input = [ 1, 2, 3, 4, ]; // This is your input array
foo(input).then(output => console.log(output));

The Promises.all is async function that takes array of promises and returns array of their results.

Array.prototype.map executes function for each item of the array.

More information:

jiwopene
  • 3,077
  • 17
  • 30
1

You can use map and Promise.all for your scenario

  const promises = raw.map(async element => {
    var elt = new Elt(element )
    elt.options = await this.getOptions(element ["id"])
    return elt
  })
  
  const yourArray = await Promise.all(promises);
Rahul Singh
  • 690
  • 1
  • 5
  • 10
1

First await the completion of the async fetching of all of the options using map and Promise.all, and then map those IDs to a list of elements, something like this:

const options = await Promise.all(raw.map(r => this.getOptions(r.id)));

const elements = options.map(option => {
    const elt = new Elt();
    elt.options = option;
    return elt;
});
jarmod
  • 71,565
  • 16
  • 115
  • 122