Delaying the activation of the code until the image upload is complete

I'm having trouble synchronizing code to upload an image using a vue composable, wait for the upload to finish, and then store the Firebase storage URL into a database. Despite getting the URL, the success code fires before the upload is complete.

My attempt below at chaining actions with then callbacks to make them synchronous isn't working as expected.

VueComponent.vue

const newImage = async () => {
      if (image.value) {
        await uploadImage(image.value);
      } else return null;
    };

    const handleSubmit = async () => {
     
      try {
      
        const colRef = collection(db, "collection");

        newImage()
          .then(() => {
            addDoc(colRef, {
              content: content.value
            });
          })
          .then(() => {
            //code to run only on success
              });
          });
       
      } catch (error) {
       
      }
    };

useStorage.js composable

import { ref } from "vue";
import { projectStorage } from "../firebase/config";
import {
  uploadBytesResumable,
  getDownloadURL,
  ref as storageRef,
} from "@firebase/storage";

const useStorage = () => {
  const error = ref(null);
  const url = ref(null);
  const filePath = ref(null);

  const uploadImage = async (file) => {
    filePath.value = `${file.name}`;

    const storageReference = storageRef(projectStorage, 
 filePath.value);

    const uploadTask = uploadBytesResumable(storageReference, 
 file);

    uploadTask.on(
      "state_changed",
      (snapshot) => {
        const progress =
          (snapshot.bytesTransferred / snapshot.totalBytes) * 
 100;
        console.log("Upload is " + progress + "% done");
      },
      (err) => {
      },
      () => {
        getDownloadURL(uploadTask.snapshot.ref).then((downloadURL) 
     => 
           {console.log("File available at", downloadURL);
      });
      }
    );
    
  };


  return { url, filePath, error, uploadImage };
};

export default useStorage;

Answer №1

Your function uploadImage does not properly wait for the upload to finish, causing the addDoc operation to occur prematurely.

const uploadImage = async (file) => {
  filePath.value = `${file.name}`;

  const storageReference = storageRef(projectStorage, 
filePath.value);

  const uploadTask = uploadBytesResumable(storageReference, 
file);

  await uploadTask; // 👈 Make sure to wait for the upload to be completed

  const downloadURL = getDownloadURL(uploadTask.snapshot.ref)

  return downloadURL;
}

To use this function correctly:

newImage()
  .then((downloadURL) => {
    addDoc(colRef, {
      content: content.value
    });
  })

Alternatively, you can use await with:

const downloadURL = await newImage();
addDoc(colRef, {
  content: content.value
});

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

transferring data between react components

I am currently working on breaking down code into smaller components, starting with the snippet below from Rows.jsx. I am struggling to grasp how props are passed between parent and child components. Despite reading several guides and articles, I remain un ...

Interactive html5 canvas game with swiping mechanism

Currently, I am in the research phase for a new HTML5 canvas game that I want to create as a personal project to enhance my skills. Surprisingly, I have not been able to find any valuable articles or tutorials online about creating swipe-based games. The ...

What is the best way to convert a query into Sequelize?

select reservation_datetime from LectureReservation Inner Join Lecture On LectureReservation.lecture_id = Lecture.id Where Lecture.mentor_id = 1 This is my initial query and now I am attempting to convert it into a sequelize format like: if (req.params ...

Can anyone explain to me why the data I'm passing as props to the React functional component is displaying as undefined?

I have encountered an issue with a pre-made React component where I am unable to see the data being passed as props when I console log it. I am unsure if I am passing the prop correctly, as I have used the same prop successfully in other class-based comp ...

Glistening tabPanel and Analytics by Google

I recently completed a comprehensive tutorial here that delves into the intricacies of Google Analytics. Despite grasping the concepts explained in the tutorial, my understanding of jQuery remains at ground zero. In my ShinyApp, I utilize multiple tabPanel ...

Steps for implementing a single proxy in JavaScript AJAX with SOAP, mirroring the functionality of the WCF Test Client

I am working with a WCF web Service and a javascript client that connects to this service via AJAX using SOAP 1.2. My goal is to pass a parameter to instruct the AJAX SOAP call to use only one proxy, similar to how it is done in the WCF Test Client by unch ...

Putting an <input/> element inside a Material UI's <TextField/> component in ReactJS - a beginner's guide

I am attempting to style <TextField/> (http://www.material-ui.com/#/components/text-field) to resemble an <input/>. Here is what I have tried: <TextField hintText='Enter username' > <input className="form-control ...

Avoiding repetitive rendering of child components in ReactJS

In my React project, I have a parent component that contains 3 children components, structured like this: var Parent = React.createClass({ render: function() { return (<div> <C1/> <C2/> <C3/> ...

Deselect the checkbox that was initially selected when an alternative checkbox option has been chosen

I am trying to implement a feature where there are 2 groups of checkbox options on the same page. Below is the code snippet: <div class="col-xs-12"> <label class="checkbox-inline"> <input type="checkbox" th:field="*{borrowerRace1}" th:val ...

Understanding JSON Parsing in Jade

I am facing a challenge with handling a large array of objects that I am passing through express into a Jade template. The structure of the data looks similar to this: [{ big object }, { big object }, { big object }, ...] To pass it into the Jade templat ...

Loading Webfonts Asynchronously in NextJS Using Webfontloader

I am currently working on a NextJS app where I am using webfontloader to load fonts dynamically. function load() { const WebFont = require("webfontloader"); WebFont.load({ google: { families: fonts } }); } However, I ha ...

A web application using JavaScript and Node.js with a focus on creating a REST

After extensive research, I am eager to develop a web application using JavaScript and Node.js with an SQL back-end. However, the abundance of frameworks and tools available has left me feeling overwhelmed. While I have identified some that I would like to ...

jquery accordion not functioning properly following partial ajax page refresh

Initially, I'm using a jQuery accordion that works perfectly. However, I encounter an issue when implementing some Ajax commands to reload part of the page, specifically the inner body section. After the page reloads, the accordion breaks because the ...

Tips for designing scrollable overlay content:

I am currently in the process of building a page inspired by the design of Hello Monday. Right now, I have added static content before implementing the parallax effect and auto-scroll. Here is my progress so far: Check out the Sandbox Link One challenge ...

Creating an identifier for the jQuery slideToggle function involves assigning a unique class or ID to

I am currently working on creating an identifier for the jQuery slide.Toggle function. In my PHP code, I have a loop that prints values, each with a button and a div that should be able to slide toggle. So far in PHP, here is what I have attempted, withou ...

Error: The call stack has reached the maximum size limit in nodejs and reactjs

When I attempt to submit the token received from my registration using the code snippet below, I encounter an error stating "maximum call stack exceeded." exports.activationController = (req, res) => { const { token } = req.body; exports.activation ...

Testing a Vuetify Data Table using Jest for unit testing

I've developed a Vue.js application utilizing Vuetify and I'm currently working on unit testing a component that contains a Vuetify Data Table. The issue arises when trying to populate the table in my unit test, where Axios is mocked with Jest. ...

Can Chrome Support Bookmarklets?

While attempting to craft a bookmarklet in Chrome using the console, I encountered the following error: Refused to load the script 'https://code.jquery.com/jquery-1.6.1.min.js' because it violates the following Content Security Policy directive: ...

Issue with React component not updating content after state changes in Next.js framework

Currently, I am facing an issue with my Header component not updating its content on state change. The goal is to show the user's Profile once the state changes, but unfortunately, it does not update immediately; it only changes after a page refresh o ...

How to disable the underline styling for autocomplete in a React Material UI component

Seeking assistance with removing underline styling and changing text color upon focus within the autocomplete component of React Material UI. Struggling to locate the specific style needing modification. Appreciate any help in advance! ...