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()?
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