1

I have an array called "clickables" that I want to map over and do something with each element. However, I want to map over it in order, and asynchronously wait. That means for this code:

 clickables = ['ele1', 'ele2', 'ele3']
 clickables.map(async ele => {
    await // action1
    await // action2
  });

I want ele1 to perform action 1 and then action 2. Ele2 will wait for ele1 to finish, and then perform action 1 and then action 2. Ele3 will wait for ele2 to finish, and so on.

Async await within the map obviously makes sure action 1 is performed before action 2 for each individual element, but it does not ensure that we wait for ele1 to finish before ele2 executes.

How can I do this?

Andrew Zaw
  • 754
  • 1
  • 9
  • 16
  • You aren't doing anything with the return value of `map` so you shouldn't be using `map` in the first place. `forEach` would make more sense, but it won't work with `async` functions in the way that you want (and nor will `map`). – Quentin Dec 13 '19 at 19:34
  • https://stackblitz.com/edit/js-vq6jcy – Saurabh Yadav Dec 13 '19 at 19:52

1 Answers1

1

I think you'd probably be better off using a loop instead of map. You could do it pretty easily like this:

clickables = ['ele1', 'ele2', 'ele3'];
(async () => {
  for (const e of clickables) {
    await console.log(`${e}-1`);
    await console.log(`${e}-2`);
  }
})();

You can supposedly use reduce for functionality like this, but it is much more complicated syntactically, and I would argue that this is much easier to follow and readable. See this CSS-Tricks article about it.

matthew-e-brown
  • 2,837
  • 1
  • 10
  • 29
  • ``clickables.reduce((p, e) => p.then(async () => { await console.log(`${e}-1`); await console.log(`${e}-2`); }), Promise.resolve())`` doesn't seem that much more complicated. – Patrick Roberts Dec 13 '19 at 19:42