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 callbackasync
.
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])