Search code examples
javascriptreactjses6-promise

How to wait for javascript loop to wait for backend call to finish


Java developer trying to learn javascript, and I'm having trouble coming up with the correct solution for my problem. I'm trying to loop through an array of objects, if the current object in the loop needs a file downloaded, then download it, and set it as a field on the object. At the end of the looping, set a reactjs state field with the array objects. I know the issue, but don't know the best way to solve it. I know the setImprintInfo is getting called before all the looping/downloadAttachment stuff is done. Thank you, and sorry if this is a rookie issue.

const setupImprintInfo = (imprints: Imprint[])  => {
        imprints.forEach(imprint => {
            if (imprint.shouldDownloadAttachment) {
                downloadAttachment(imprint.id)
                    .then(blob=> {
                        imprint.attachment = blob
                    })
            }
        })

        setImprintInfo({imprints: imprints})
    }

Solution

  • Backend function having promise

    function backendPromiseFunc(data) {
      return new Promise((resolve, reject) => {
        if (Number.isInteger(data)) {
          resolve(`${data}`);
        } else {
          reject(`Invalid value: ${data}`);
        }
      });
    }
    

    Then Async function for asynchronous request return at the end of data array to stop the loop

    async function backendLoopCall() {
      const numArray = [1, 2, 3, 4, 'hello'];
      
      for (const data of numArray) {
        console.log(`Processing: ${data}`);
        try {
          const result = await backendPromiseFunc(data);
          console.log(`Received result: ${result}`);
        } catch (error) {
          console.log(`Received error: ${error}`);
        }
      }
      return;
    }
    

    lastly call invoke the function

    backendLoopCall();
    

    precisely your code should look like this and have to have promise function in the backend for this

    const setupImprintInfo = async (imprints: Imprint[]) => {
        for (const imprint of imprints) {
            if (imprint.shouldDownloadAttachment) {
                try {
                    const blob = await downloadAttachment(imprint.id);
                    imprint.attachment = blob;
                } catch (error) {
                    console.error('Error downloading attachment', error);
                }
            }
        }
    
        setImprintInfo({ imprints: imprints });
    }
    

    I hope it helps!