How to delay a function until after a forEach statement completes?

I am currently working on a messaging application using React. At the moment, I am struggling with determining a method of delaying the main function that posts a message to the chat.

The main issue is working with the Cloudinary API, for picture message submission, I need the urls that are spit out from the POST request.Thus, I also need the postMessage method to be delayed until after my photos have been uploaded to Cloudinary Database, and the ‘temp’ array has collected the new generated image urls. My issue begins and most likely ends with the fact that I cannot determine the proper way to delay postMessage until my forEach statement completes.

Here is the code for my handleSubmit Method:

const handleSubmit = async (event) => {
    event.preventDefault();

    const formElements = event.currentTarget.elements;
    const formData = new FormData();
    let temp = [];

    if (imagesSelected.length > 0) {
      imagesSelected.forEach((image) => {
        formData.append('file', image);
        formData.append('upload_preset', 'sendpics');
        
        instance.post('https://api.cloudinary.com/v1_1/dg7d5il8f/image/upload', formData )
        .then((res) => {
          temp.push(res.data.url);
        })
        .catch((err) => {
          console.log(err);
        });
      });

      const reqBody = {
        text: formElements.text.value,
        recipientId: otherUser.id,
        conversationId,
        sender: conversationId ? null : user,
        attachments: temp,
      };
          
      postMessage(reqBody);
    } else {
      const reqBody = {
        text: formElements.text.value,
        recipientId: otherUser.id,
        conversationId,
        sender: conversationId ? null : user,
        attachments: [],
      };
          
      postMessage(reqBody);
    }

    setText('');
    setImagesSelected(() => []);
  };

The issue remains in the first if statement, as once the forEach statement triggers, postMessage triggers right after, before temp even has a chance to be populated with the new url values. Apologies if the whole question itself is convoluted by any means. Please comment if I need to clarify anything about my question. Thanks for any help/suggestions!

>Solution :

I think you’ll need to await them with for-of loop using-async-await-with-a-foreach-loop
An example with your case:

for (const image of imagesSelected) {
  //...
  try {
    const resp = await instance.post(
      "https://api.cloudinary.com/v1_1/dg7d5il8f/image/upload",
      formData
    );
    temp.push(resp.data.url);
  } catch (error) {
    console.log(error);
  }
}

Another approach is replacing forEach with map and adding Promise.all As E. Shcherbo mentioned in comments

Leave a Reply