Home > Back-end >  Using async/await in a loop
Using async/await in a loop

Time:09-17

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
  • Related