Fabio Marzocca
Fabio Marzocca

Reputation: 1677

Ordered forEach loop

I have an Array of elements and I need to loop over them getting a value from a server at each pass. With the following code I am getting all the results mixed, due to the asynchronous call in the forEach loop. I need the results to be shown in the same order as in the Array.

var en_devices= [
  ["72", "Device 1"],
  ["73", "Device 2"],
  ["74", "Device 3"],
  ["75", "Device 4"],
  ["76", "Device 5"],
  ["5158", "Device 6"]
];

en_devices.forEach(element => {
    $.get('/check-energy/'+element[0], function(data){
      content = "<div class='service'>"+element[1]+"</div> <div class='watt'>"+data+"</div><br/>";
      $('#description-en').append(content);
  });
 });

Upvotes: 0

Views: 110

Answers (2)

Łukasz Nojek
Łukasz Nojek

Reputation: 1641

If $.get is jQuery.get() then it returns a promise and you can use asynchronous programming.

As @CherryDT said, utilize it in an async function. If you don't have one, use it an IIFE - Immediately Invoked Function Expression:

(async () => {
  for (let element of en_devices) {
    const data = await $.get('/check-energy/' + element[0]);
    const content = "<div class='service'>" + element[1] + "</div> <div class='watt'>" + data + "</div><br/>";
    $('#description-en').append(content);
  }
})();

UPDATE:

As @huyts pointed, the above method calls the API one at time. To make it parallel, use Promise.all:

(async () => {
  const promises = en_devices.map(element =>
    $.get('/check-energy/' + element[0])
    .then(data => [element[1], data])
  );

  const results = await Promise.all(promises);
  for (let result of results) {
    const content = "<div class='service'>" + result[0] + "</div> <div class='watt'>" + result[1] + "</div><br/>";
    $('#description-en').append(content);
  }
})();

Upvotes: 2

huytc
huytc

Reputation: 1141

See Promise.all.

const en_devices= [
  ["72", "Device 1"],
  ["73", "Device 2"],
  ["74", "Device 3"],
  ["75", "Device 4"],
  ["76", "Device 5"],
  ["5158", "Device 6"]
];

const length = en_devices.length;
const promises = [];
const results = Array(length).fill(null);

en_devices.forEach((element, index) => {
    promises.push(
        new Promise((resolve, reject) => {
            $.get('/check-energy/'+element[0], function(data){
                content = "<div class='service'>"+element[1]+"</div> <div class='watt'>"+data+"</div><br/>";
                results[index] = content;
                resolve();
            }
        })
    );
});

Promise.all(promises).then(() => {
    for (const result of results) $('#description-en').append(result);
});

Upvotes: 0

Related Questions