1

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

0

1 Answer 1

2

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
Sign up to request clarification or add additional context in comments.

2 Comments

That is my mistake. I changed the code a little before I posted the question to make it simpler but it's actually important to have it the way it was. I updated the original question. The order does matter, sort of. The resulting structure is an object, not an array. It is in the same format as the refs object: 2 keys with arrays as values.
Awesome! That’s exactly what I was trying to do. Thanks for the help.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.