Tips for delaying the execution of the next function until after a Firebase storage image upload is complete

I'm currently working on a function that involves uploading multiple images to Firebase, storing the returned URLs in an object, and then uploading that object to my Cloud Firestore database. However, my understanding of async/await and promises is limited, so any assistance would be greatly appreciated.

Essentially, I want the uploadImages() function to complete its execution before triggering the uploadData() function, which will further call the saveIssue() function upon form submission.

Below is the code snippet I am dealing with:

saveIssue() {
  this.uploadImages();
  this.uploadData();
},
uploadData() {
  let self = this;
  db.collection("issues")
    .add(self.issue)
    .then(docRef => {
      self.$router.push({
        name: "ReportPage",
        params: { issueId: docRef.id }
      });
    })
    .catch(error => {
      console.error(error);
    });
},
uploadImages() {
  const storageRef = storage.ref();
  let self = this;
  this.imagePreviews.forEach(image => {
    let imageName = uuidv1();
    let fileExt = image.fileName.split(".").pop();
    let uploadTask = storageRef
      .child(`images/${imageName}.${fileExt}`)
      .putString(image.base64String, "data_url");
    uploadTask.on("state_changed", {
      error: error => {
        console.error(error);
      },
      complete: () => {
        uploadTask.snapshot.ref.getDownloadURL().then(downloadURL => {
          self.issue.images.push(downloadURL);
        });
      }
    });
  });
},

Answer №1

For integrating promises into your code, refer to the explanation here. To incorporate async wait functionality with Firebase support, you can start by following this structure:

async saveIssue() {
    await this.uploadImages();
    await this.uploadData();
  },
  uploadData() {
    return new Promise((resolve, reject) => {
      let self = this;
      db.collection("issues")
        .add(self.issue)
        .then(docRef => {
          self.$router.push({
            name: "ReportPage",
            params: {
              issueId: docRef.id
            }
          });
          resolve();
        })
        .catch(error => {
          console.error(error);
          reject(error);
        });
    })
  },
  uploadImages() {
    return new Promise((resolve, reject) => {
      const storageRef = storage.ref();
      let self = this;
      this.imagePreviews.forEach(image => {
        let imageName = uuidv1();
        let fileExt = image.fileName.split(".").pop();
        let uploadTask = storageRef
          .child(`images/${imageName}.${fileExt}`)
          .putString(image.base64String, "data_url");
        uploadTask.on("state_changed", {
          error: error => {
            console.error(error);
            reject(error);
          },
          complete: () => {
            uploadTask.snapshot.ref.getDownloadURL().then(downloadURL => {
              self.issue.images.push(downloadURL);
              resolve();
            });
          }
        });
      });
    })
  },

Answer №2

After consulting @AlexBrohshtut's answer, I was able to come up with a solution for my issue. However, I encountered a problem where the await statement would continue after the first loop finished. The code snippet below appears to have resolved that issue. I am open to suggestions for a more concise solution! (I consider myself an intermediate coder at best...)

 resolveIssue() {
  Promise.all(
    this.imagePreviews.map(async image => {
      return await this.uploadImages(image);
    })
  ).then(() => {
    this.updateData();
  });
},
updateData() {
  let self = this;
  db.collection("issues")
    .add(self.issue)
    .then(docRef => {
      self.$router.push({
        name: "ReportPage",
        params: {
          issueId: docRef.id
        }
      });
    })
    .catch(error => {
      console.error(error);
    });
},
uploadImages(image) {
  const storageRef = storage.ref();
  let self = this;
  return new Promise((resolve, reject) => {
    let imageName = uuidv1();
    let fileExt = image.fileName.split(".").pop();
    let uploadTask = storageRef
      .child(`images/${imageName}.${fileExt}`)
      .putString(image.base64String, "data_url");
    uploadTask.on("state_changed", {
      error: error => {
        console.error(error);
        reject(error);
      },
      complete: () => {
        uploadTask.snapshot.ref.getDownloadURL().then(downloadURL => {
          self.issue.images.push(downloadURL);
          resolve();
        });
      }
    });
  });
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Determining the Next Available Date from JSON Data

I have a task of using a JSON response from the Eventbrite API to showcase the upcoming event tour date. The goal is to automatically calculate this date based on the current time, identifying the next event after the current moment. Below is the JSON res ...

Invoking a synchronous JavaScript request to an MVC 4 Controller function

For the code I'm working on, I need certain functions to be executed sequentially. I attempted to use ajax calls but ran into issues due to their asynchronous nature. function GetLibraryActivities(libraryName, callback) { $.ajax({ dataTyp ...

Troubleshooting problems with deploying a full stack application on Azure Static Web Apps

I've been struggling with this issue for a week now and any suggestions would be greatly appreciated! I'm working on a catalog website for a client. My server and database are hosted on Azure SQL, while the frontend is built using vue.js compiled ...

An issue has been identified where the 'connect' event in socket.io does not trigger on the client side

Looking to dive into the world of node.js and socket.io. I've put together a simple client-server test application, but unfortunately it's not functioning as expected. Running the system on a Windows machine with an Apache server setup. Apa ...

What is the best way to create and deliver favicons using Webpack?

Currently, I am working on a universal React project and I need to serve favicons in an Html.js component that is rendered server-side. I came across this package which automatically generates over 30 different sizes of favicons, and I am interested in us ...

Update the Material-UI theme to a personalized design

I am currently using Material-UI in my React project. However, I'm facing some difficulties in applying a theme globally. Up until now, I have only managed to apply the theme to individual components like this: import { MuiThemeProvider, createMuiTh ...

Use the JavaScript executor to combine a dynamic string

I have a String variable that retrieves IDs from an Excel sheet. String id = formatter.formatCellValue(sheet.getRow(i).getCell(2)); I am trying to dynamically update the ID using JavaScript executor, but it seems that the concatenation is not working cor ...

Flowbite components are visually appealing, but unfortunately, the interactions are not functioning properly

I am experiencing issues with all flowbite components. The problem lies in the fact that while the components load, the interactions do not work. For example, this accordion remains open and I am unable to close or open it. Similarly, the modals and carou ...

Error received when attempting AJAX call with jQuery 1.7.2: NS_ERROR_XPC_NOT_ENOUGH_ARGS

Encountering an issue with jQuery version 1.7.2 and the ajax function. When running the code snippet below, Firefox Firebug console displays the following error: NS_ERROR_XPC_NOT_ENOUGH_ARGS: Not enough arguments [nsIDOMLocation.replace] var wei ...

Tips for setting background colors as a prop for Material UI cards in React JS

Currently utilizing the Material UI next framework to construct a wrapper for the card component. This customized wrapper allows for personalization of the component. I have successfully extended the component so that the title and image within the card ca ...

Decrease the gap between the columns within the card

https://i.sstatic.net/cNqrE.png Could you please help me figure out how to estimate the distance between each column in this shape? I am looking to approximate the space between each blue piece. Any suggestions on how to achieve this? Code snippet - Card ...

Using Tailwind classes in Vue props

Looking to utilize a Vue prop within a Tailwind CSS class. The class in question is bg-[url('address')] (which sets the background image), with 'address' being the prop. Despite various attempts, I keep encountering the following erro ...

Alan AI does not support installation on React Native

❯ To install the @alan-ai/alan-sdk-react-native package, run: sudo npm i @alan-ai/alan-sdk-react-native --save > Post installation for @alan-ai/contact: > Copying AlanSDK.js, AlanButton.js, and AlanText.js to destination Mak ...

Align the object with the path it is following

Currently, I am in the process of learning about vectors and their application in moving objects within ThreeJS. For an experiment, I am propelling a box using a specified velocity and an arbitrary gravity vector. Additionally, I am attempting to align th ...

"Sending a file (Image) through NextJS API Routes to an external API: A step-by-step guide

I am currently using a combination of NextJS (SSR and SPA for authorized dashboard) with Django Rest FW on the backend. To handle authentication, I employ JWT tokens stored in cookies. As a result, it is necessary to have a middleware at /pages/api/* that ...

Change the output of Object.fromEntries

I've been working on updating the values of an object using the .fromEntries() method. The issue I am facing is that even though I am returning a modified Array of hours, when the function completes it reverts back to the original complete Array. If ...

Retrieve the document id along with the corresponding data from a collection

Retrieving data from the collection leads and displaying all documents in an HTML table. Upon clicking, I need to extract the document ID of the clicked item as it serves as the sole primary key. P.S I am able to obtain records of all documents in an arra ...

What causes my input field to lose focus in React.js after typing just one character?

My react.js component is experiencing an issue where the input field loses focus whenever a character is typed. To continue typing or editing, I have to click on the input field again. What could be causing this problem? Below is the code snippet in quest ...

Storing a reference within another reference can diminish its reactivity

I'm encountering an issue with nested refs. Whenever I try to access the inner refs, I only receive back the values instead of the reactive variables. My situation involves a Pinia store, but I've simplified it down to the essential components. ...

[code=access-denied]: Access denied for this project resource

Encountering a firebase error: https://i.sstatic.net/IVq7F.png In my project using react-hooks-firebase, with react and TypeScript, I encountered an issue after adding true to the firebase database... https://i.sstatic.net/5gQSD.png firebase.ts: After ...