Home > Net >  Wait for a Javascript function to finish executing and fetch the response from it
Wait for a Javascript function to finish executing and fetch the response from it

Time:06-12

I've a array of images and I am uploading these images to firebase storage.

      data = {
        ...data,
        downloadedUrl: [],
      };
    
      if (data?.image?.length) {
        for (const image of data?.image) {
          await uploadFile(image, data);
        }
      }

uploadFile handles the logic for uploading the image to firebase.

  const uploadFile = useCallback((file, data) => {
    if (!file) return;

    const storageRef = ref(storage, `/images/${file.name}`);
    const uploadTask = uploadBytesResumable(storageRef, file);

    uploadTask.on(
      "state_changed",
      (snap_shot) => {},
      (err) => console.log(err),
      async () => {
        await getDownloadURL(uploadTask.snapshot.ref).then((url) => {
          data.downloadedUrl.push(url);
        });
      }
    );
  }, []);

It takes few seconds to get the downloadedUrl from uploadTask and I want to store this downloadedUrl in firebase firestore when I get all the urls.

Issue with the current approach is that before getting the urls, the other function start executing and I am not able to upload this data on firestore with the downloadedUrl Here's the full function when someone clicks on form submit

const handleFormSubmit = useCallback(
    async (data) => {
      setLoading(true);
      data = {
        ...data,
        downloadedUrl: [],
      };

      if (data?.image?.length) {
        for (const image of data?.image) {
          await uploadFile(image, data);
        }
      }

      if (data.downloadedUrl.length) {
        uploadDataToFirestore(data);
      }
 
      if (!data.downloadedUrl?.length) {
        dispatch(handleAlertState({ message: "Error Occured!!!" }));
        router.push("/services");
        return;
      }
      setLoading(false);
      router.push("/");
    },
    [dispatch, router, uploadDataToFirestore, uploadFile]
  );

  const uploadDataToFirestore = useCallback(
    async (data) => {

      await setDoc(doc(db, "form-responses"), data)
        .then((response) => {
          console.log("response", response);
          dispatch(
            handleAlertState({
              message: "Success. Your request has been sent. Thank You.",
            })
          );
        })
        .catch((error) => {
          console.log("error", error);
        });
    },
    [dispatch]
  );

This bellow block of code executes the code while images are being uploaded to the cloud storage. I want to wait for the downloadedUrl and then upload the urls to firebase firestore.

      if (!data.downloadedUrl?.length) {
        dispatch(handleAlertState({ message: "Error Occured!!!" }));
        router.push("/services");
        return;
      }

CodePudding user response:

  1. Create array of promises
  2. Use Promise.all to watch for every promise

const uploadFile = useCallback((file, data) => {
  return new Promise((resolve, reject) => {
    if (!file) reject();

    const storageRef = ref(storage, `/images/${file.name}`);
    const uploadTask = uploadBytesResumable(storageRef, file);

    uploadTask.on(
      'state_changed',
      snap_shot => {},
      err => reject(err),
      async () => {
        await getDownloadURL(uploadTask.snapshot.ref).then(url => {
          resolve(url);
          //data.downloadedUrl.push(url);
        });
      },
    );
  });
}, []);

let allPromises = [];
if (data?.image?.length) {
  for (const image of data?.image) {
    allPromises.push(uploadFile(image, data));
  }
}

let uploadedUrls = await Promise.all(allPromises);
console.log(uploadedUrls);

  • Related