Home > Software engineering >  How to make map work asynchronously using Promise?
How to make map work asynchronously using Promise?

Time:09-07

I want to make map run asynchronously. I tried using async and Promise.all but I not sure where I am going wrong. This is code I have written

// this is the id => [1,2,3] and total of each => [2, 3, 2]
useEffect(()=> {
  countNumFunc(idList)
})

const countNumFunc = (idlist) => {
  let count = 0
  Promise.all(idList.map(async (id) => {
    console.log("id = ", id)
    getInfoFromDb(id).then((res) => {
      if(res.data) {
        count = count   res.data.total
        console.log("Count = ", res.data.total)
      }
    }).catch(error => {
        console.log("error = ", error)
    })
  }))
  console.log("Count total = ", count)
} 

Here the output should have been:

id = 1
Count = 2
id = 2
Count = 5
id = 3
Count = 7
Count total = 7

But the output is:

id = 1
id = 2
id = 3
Count total = 0
Count = 2
Count = 3
Count = 2

CodePudding user response:

To get the desired result you should:

  • not use Promise.all: Promise.all is when you want to create all promises first and then await them. But from your desired output it shows you want to create the promises (do the DB queries) one by one, each time waiting for the previous one to resolve.

  • not use .map(). First of all, .map() returns an array. If you have no use for that array, then don't use .map(). Secondly, .map() will make all iterations synchronously -- it doesn't help to make its callback async.

Instead declare countNumFunc as an async function, loop with for..of, and await the value that getInfoFromDb(id) will resolve to.

Secondly, you seem to want to show a running count, so then you should not display res.data.total, but just count:

// Mock:
const getInfoFromDb = async (i) => ({ data: {total: [0, 2, 3, 2][i]} });

const countNumFunc = async (idList) => {
  let count = 0
  for (let id of idList) {
    console.log("id = ", id)
    const res = await getInfoFromDb(id);
    if(res.data) {
        count = count   res.data.total
        console.log("Count = ", count)
    }
  }
  console.log("Count total = ", count)
} 

countNumFunc([1,2,3])

  • Related