1

I am trying to rewrite this async loop using map but I can't achieve the desired result

const wait = (ms) => new Promise((r) => setTimeout(r, ms));
const numbers = [1, 2, 3, 4, 5];
const loop = async() => {
  for (const number of numbers) {
    console.log(number);
    await wait(500);
  }
};
loop();

But when I try:

const wait = (ms) => new Promise((r) => setTimeout(r, ms));
const numbers = [1, 2, 3, 4, 5];
const loop = async() => {
  numbers.map(async(number) => {
    console.log(number);
    await 500;
  });
};
loop();

It gives sync behavior!

Can you tell me where is the mistake please?

solimanware
  • 2,952
  • 4
  • 20
  • 40
  • 1
    `Array.prototype.map` doesn't `await` the passed function. You'd notice you get an array of `Promise`s, if you didn't abuse it for iteration. – ASDFGerte Dec 17 '21 at 17:47
  • why would you want to do that? – epascarello Dec 17 '21 at 17:48
  • What do you mean by "*it gives sync behavior*"? – Bergi Dec 17 '21 at 17:55
  • I would assume he means numbers don't show with the delay of 500ms one after another. – Nenad Vracar Dec 17 '21 at 17:56
  • It's not possible to rewrite it using `map`. Using `map` is not rewriting but completely changing the behavior form sequentially waiting to waiting in parallel. If you want to rewrite it you need to write a recursive function. – slebetman Dec 17 '21 at 18:03
  • @slebetman `reduce` can also do it. If *really* needed, I'd opt for that rather than recursion. But I'm not sure when I'd use it over a normal loop. – VLAZ Dec 17 '21 at 18:05
  • @VLAZ How? Reduce works exactly like map in that it accepts a callback and within that callback you cannot await properly (sequentially). If you say reduce can do it then map also can. In which case feel free to write that as an answer (map that is) because that's exactly what the OP wants. – slebetman Dec 18 '21 at 02:32
  • @slebetman `arr.reduce((p, x) => p.then( x => console.log(x) ).then( () => wait(500) ), Promise.resolve())` - just reduce them into a promise chain. Then it's going to be sequential. – VLAZ Dec 18 '21 at 07:42
  • Here's an equivalent using for-loop `const wait = (ms) => new Promise((r) => setTimeout(r, ms)); const numbers = [1, 2, 3, 4, 5]; const loop = () => { let promise = Promise.resolve(); for (const number of numbers) { promise = promise.then(() => { console.log(number); return wait(500); }); } }; loop();` – Gandalf Feb 23 '23 at 08:48

0 Answers0