0

I'm wondering what's the best method to loop over an array and use async/await on the elements as you perform a task with them. Being new to the language, I haven't found a definitive answer or I didn't understand the solution (using Promise.all with and map method ?)

This is the code. renderCountry is NOT an async function, but the function where this condition happens is an async. Is it correct how I've done it? If not, how should I implement it? I just wanna make sure the code is non-blocking as I loop over the array's elements,

Code

if (neighboursArr) {
  neighboursArr.forEach(async (el, i) => {
    await wait(i * 300);
    const neighbourRes = await fetch(
      `https://restcountries.com/v3.1/alpha/${el}`
    );
    const neighbourData = await neighbourRes.json();
    renderCountry(neighbourData[0], "neighbour");
  });
} else {
  renderMessage("It is lonely island :)");
}
Wick
  • 1
  • 3

1 Answers1

-1

Well, disregarding your specific code, while focusing the main general question you posed in the first paragraph, I have devised a way for async iteration:

const delay = ms => new Promise(resolve => setTimeout(resolve, ms))
const inc = async i => (await delay(500), ++i)

const foo = async () => {
  for(let i = 1; i <= 5; i = await inc(i)) 
    console.log(i) // prints 1, 2, 3, 4, 5 with a delay 
}

foo()

Above code is from my Github gist

vsync
  • 118,978
  • 58
  • 307
  • 400
  • @bergi - I think the main question is not focused on `forEach`, which is just an example of the OPs implementation, but a general question about delayed iterations, and so, the duplicate question you found is specific to `forEach` and so, narrows down this question instead of keep it broad (and more interesting IMHO) – vsync Feb 05 '23 at 17:43
  • 1
    @vsync I can add https://stackoverflow.com/questions/3583724/how-do-i-add-a-delay-in-a-javascript-loop if you prefer. However, I don't think the OP is interested about specifically delaying loops - they are asking for the "*best method to loop over an array and use async/await on the elements as you perform a task with them.*", which is perfectly answered in the current duplicate. – Bergi Feb 05 '23 at 17:45
  • @Bergi - yes, it better fits I believe – vsync Feb 05 '23 at 17:47
  • @Bergi so isn't better to use Promise.all() on the mapped items ? – Wick Feb 05 '23 at 17:49
  • @Wick There is no "better". They're simply different. One style is concurrent, the other sequential. Use the one you need/want to choose. – Bergi Feb 05 '23 at 17:50
  • @Wick - you can also use [`allSettled`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/allSettled) to iterate only successful promises. – vsync Feb 05 '23 at 17:52
  • @vsync Actually I have a hard time transforming my code using your idea. Can you help please? – Wick Feb 05 '23 at 18:09
  • @Wick - I feel you are forcing a solution without clearly outlining the problem. Maybe what you're asking for is not really what you need? please explain in-detail what is it you're trying to achieve (edit your post) – vsync Feb 05 '23 at 18:30
  • @vsync done. I just wanna know if my implementation is correct and if not, how should it be – Wick Feb 05 '23 at 19:25