How can you combine multiple async file uploads and be able to reference and write BOTH newly created URLS to database at same time?

Viewed 77

I'm working on this "postAPI" where the payload it takes in can contain up to (2) separate files.

Once the payload containing the files is dispatched to postAPI. I need it to upload the files to a firebase storage bucket and then save/write the URLs after that is successful.

I can get it working now if I limit it to be either one file or the other with the code shown below.

My problem is if there are both files, I can't reference / pass the newly uploaded URL that gets returned to the second process. Here is some code to help explain.

Here is basically how I have it split up currently:

export function postAPI(payload) {
  return (dispatch) => {
    dispatch(setLoading(true));

    if (payload.firstDoc !== "") {
      const upload = storage
        .ref(`documents/${payload.firstDoc.name}`)
        .put(payload.firstDoc);
      upload.on(
        "state_changed",
        (snapshot) => {
          const progress =
            (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
          console.log(`Progress: ${progress}%`);
          if (snapshot.state === "RUNNING") {
            console.log(`Progress: ${progress}%`);
          }
        },
        (error) => console.log(error.code),
        async () => {
          const downloadURL = await upload.snapshot.ref.getDownloadURL();
          db.collection("articles").add({
            data: payload.data,
            firstDoc: downloadURL,
            secondDoc: "",
          });
          dispatch(setLoading(false));
        }
      );
    } 

    if (payload.secondDoc !== "") {
        const secondUpload = storage
          .ref(`documents/${payload.secondDoc.name}`)
          .put(payload.secondDoc);
        secondUpload.on(
          "state_changed",
          (snapshot) => {
            const progress =
              (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
  
            console.log(`Progress: ${progress}%`);
            if (snapshot.state === "RUNNING") {
              console.log(`Progress: ${progress}%`);
            }
          },
          (error) => console.log(error.code),
          async () => {
            const secondDownloadURL = await secondUpload.snapshot.ref.getDownloadURL();
            console.log(downloadURLpod);
            db.collection("articles").add({
                data: payload.data,
                firstDoc: "",
                secondDoc: secondDownloadURL,
            });
            dispatch(setLoading(false));
          }
        );
      }
  }
}

I can't figure out how to store and/or pass the first 'downloadURL' to be available inside the second process.

Basically I just need a way to be able to have access to both downloadURL and secondDownloadURL simultaneously for the same db.add().

Thanks in advance!

1 Answers

Just use the upload as Promise and not as upload task. That way you can simply await them until each of them finishes. It would look like this:

export async function postAPI(payload) {
  return async (dispatch) => {
    dispatch(setLoading(true));

    let downloadURL1 = null;
    let downloadURL2 = null;

    if (payload.firstDoc !== "") {
      const snapshot1 = await storage
        .ref(`documents/${payload.firstDoc.name}`)
        .put(payload.firstDoc);

      const downloadURL1 = await snapshot1.ref.getDownloadURL();
    }

    if (payload.secondDoc !== "") {
      const snapshot2 = await storage
        .ref(`documents/${payload.secondDoc.name}`)
        .put(payload.secondDoc);

      const downloadURL2 = await snapshot2.ref.getDownloadURL();
    }

    db.collection("articles").add({
      data: payload.data,
      firstDoc: downloadURL1,
      secondDoc: downloadURL2,
    });
    dispatch(setLoading(false));
  };
}
Related