I know there are a lot of similar questions out there already but none of them seem to solve this specific problem. I have a Javascript function that contains a forEach loop and inside the forEach loop, there are asynchronous calls.
The code roughly looks like this:
const handleConvert = () => {
const refs = { ...imageRefs.current }
// Outer loop
Object.keys(refs).forEach(key => {
// Inner loop
refs[key].forEach(ref => {
toPng(ref)
.then((dataUrl) => {
props.setImageUrls(old => {
return {
..old,
[key]: [...old[key], dataUrl]
}
})
})
.catch(err => {
console.error(err)
})
})
})
setConverting(false)
setConverted(true)
}
refs
is an object that contains 2 keys and each key has an array for it's value. It looks something like this:
{
a: [1, 2, 3],
b: [3, 4, 5]
}
The toPng() function returns a promise. I am trying to wait for all of those promises to resolve before executing the code after the outer forEach loop:
if (mounted) {
setConverting(false)
setConverted(true)
}
Is there a way to wait for all the promises to resolve before executing the code after the outer loop? Maybe with Promise.all()?
CodePudding user response:
Nest another Promise.all
to wait for each subarray to finish. Make sure to map and return every Promise to the caller so the Promise.all
functions properly.
Promise.all(
Object.entries(refs)
.map(([key, arr]) => Promise.all(
arr.map(num =>
toPng(num).then(dataUrl => {
props.setImageUrls(old => ({ ...old, [key]: [...old[key], dataUrl] }))
})
)
))
)
.then( // all done