Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Iterate over the entries of a Map with an asynchronous callback function

Tags:

javascript

I want to iterate the entries of a Map with an asynchronous callback function. The callback function should be started immediately for all elements.

I ended up with the following code, which works but looks too complicated:

async function test() {
  const map1 = new Map();

  map1.set('a', 1);
  map1.set('b', 2);
  map1.set('c', 3);

  await Promise.all(Array.from(map1.entries()).map(async([
    key,
    value
  ]) => {
    await doSomeThing(key, value);
    await doSomeOtherThing(key, value);
  }
}

Is there an easier way to achieve this?

like image 954
Adrian Dymorz Avatar asked Oct 17 '25 09:10

Adrian Dymorz


2 Answers

You could do something shorter

  • Array.from(map1.entries()) could be rewritten to [...map1]
  • from what I see, doSomeOtherThing does not depend on doSomeThing so we could call them two concurrently
await Promise.all(
  [...map1].flatMap(([key, val]) => [
    doSomeThing(key, val),
    doSomeOtherThing(key, val),
  ])
)

const doSomeThing = (key, val) =>
  new Promise(res => {
    console.log("doSomeThing start", key, val)
    setTimeout(() => {
      console.log("doSomeThing finish", key, val)
      res()
    }, 1000)
  })
const doSomeOtherThing = (key, val) =>
  new Promise(res => {
    console.log("doSomeOtherThing start", key, val)
    setTimeout(() => {
      console.log("doSomeOtherThing finish", key, val)
      res()
    }, 2000)
  })

async function test() {
  const map1 = new Map()

  map1.set("a", 1)
  map1.set("b", 2)
  map1.set("c", 3)

  /*
  await Promise.all(
    Array.from(map1.entries()).map(async ([key, value]) => {
      await doSomeThing(key, value)
      await doSomeOtherThing(key, value)
    })
  )
  */

  await Promise.all(
    [...map1].flatMap(([key, val]) => [
      doSomeThing(key, val),
      doSomeOtherThing(key, val),
    ])
  )
}

test().then(() => {
  console.log("done")
})
like image 84
hgb123 Avatar answered Oct 19 '25 21:10

hgb123


According to MDN, Promise.all() takes an iterable of promises and waits for them to resolve. An iterable may be an array, as in your code, or a dedicated generator created by a generator function. I don't know if this meets your definition of "easier", but here's one way to do it:

function* processMap(map, callback) {
    for (const entry of map.entries())
        yield callback(entry);
}

async function test() {
    const map = new Map();
    map.set("a", 1);
    map.set("b", 2);
    map.set("c", 3);
    
    const processEntry = async (entry) => {
        await doSomeThing(entry);
        await doSomeOtherThing(entry);
    };
    
    await Promise.all(processMap(map, processEntry));
}
like image 39
Lachcim Avatar answered Oct 19 '25 23:10

Lachcim



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!