Storing a collection of images simultaneously in Firebase Storage and saving their URLs in a Firestore document using Firebase v9

I am currently working on a form that requires users to input data in order to generate a detailed city document. Additionally, users must upload multiple photos of the city as part of this process. Once the form is submitted, a new city document is created in firestore. Each photo is then uploaded to firebase storage and a new field called photosURLs, containing all the URLs of the uploaded photos, is added to the city document.

Below is the code I have written:

async function addDocument() {
    const docRef = await addDoc(collection(db, "cities"), {
        name: "Tokyo",
        country: "Japan"
      });
    return docRef
}

async function UploadMultiplePhotos(docRef) {
    var photos = []
    for (var i = 0; i < files.value.length; i++) { // files.values contains all the files objects
        const file = files.value[i];
        refStorageFunction(
            storage,
            "cities/" +
            docRef.id +
            "/" +
            file.name
          );
        uploadBytes(storageRef, file).then((snapshot) => {
            getDownloadURL(snapshot.ref).then((downloadURL) => {
                photos.push(downloadURL)
            });
        });
    }
    return Promise.resolve(photos)
}

async function updateDocument(docRef, photos) {
    await updateDoc(docRef, { photosURLs: photos });
}

function createCity() {
    addDocument().then((docRef) => {
        UploadMultiplePhotos(docRef).then((photos) => {
            updateDocument(docRef, photos).then(() => {
                router.push($CITY_PATH)
            })
        })
    })
}

However, I am encountering an issue where the resulting photosURLs field in the city document remains empty. It appears that my UploadMultiplePhotos function does not properly wait for the photos array to be fully populated.

Answer №1

By setting breakpoints and utilizing a debugger, or incorporating strategic log statements, it becomes evident that the return Promise.resolve(photos) executes prior to the photos.push(downloadURL) being triggered; resulting in consistently resolving with an empty array.

An effective solution involves substituting await for then():

async function UploadMultiplePhotos(docRef) {
    var photos = []
    for (var i = 0; i < files.value.length; i++) { // files.values contains all the files objects
        const file = files.value[i];
        refStorageFunction(
            storage,
            "cities/" +
            docRef.id +
            "/" +
            file.name
          );
        const snapshot = await uploadBytes(storageRef, file)
        const downloadURL = await getDownloadURL(snapshot.ref)
        photos.push(downloadURL)
    }
    return photos
}

Answer №2

This code snippet is optimized for using firebase v9:

        const promises = [];
        const storage = getStorage();

        for (var i = 0; i < files.length; i++) {
            const file = files[i];
            if (file !== null) {
                const storageReference = ref(storage, `path-to-your-storage-location`);

                promises.push(uploadBytesResumable(storageReference, file).then(uploadResult => {
                    return getDownloadURL(uploadResult.ref)
                }))
            }

        }
        // Retrieve all the downloadURLs
        const images = await Promise.all(promises);
        
        // Update Firestore with the URLs array
        try {
            await setDoc(answerRef, {
                supportImages: images
            }, {merge: true}).then(result => {
                console.log('Operation completed successfully')
            });
        } catch (error) {
            alert(error)
        }

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

The Express middleware type cannot be assigned as expected

I'm encountering an error where my first middleware is being red underlined. I can't figure out why it's only happening to the first one. Can anyone provide some guidance on this issue? I'm still quite new to TypeScript. Did I overloo ...

"Exploring the world of Typescript's return statements and the

I'm currently grappling with a design dilemma in typescript. Within my controller, I perform a validation process that can either return a 422 response, which ends the thread, or a validated data object that needs to be utilized further. Here's a ...

What is the best way to trigger dependent APIs when a button is clicked in a React Query application

On button click, I need to call 2 APIs where the second query depends on the result of the first query. I want to pass data from the first query to the second query and believe using "react-query" will reduce code and provide necessary states like "isFetch ...

The Art of Div Switching: Unveiling the Strategies

I have a question regarding my website. I have been working on it for some time now, but I have encountered a challenge that I am struggling to overcome. After much consideration, I am unsure of the best approach to take. The issue at hand is that I have ...

Tips for keeping data on a page up-to-date using Node.js and Express

Currently delving into the world of Node.js and Express, I am immersed in a project that involves pinging websites and exhibiting the results on a web page. Leveraging HoganJS for templating as well. My primary focus is to decipher the steps necessary to m ...

Unable to display an image fetched from Django API within VueJs

Can anyone help with rendering an image from Django RestAPI to Vuejs Frontend? I am able to retrieve all model elements in VueJS, but encountering issues when it comes to rendering images. invalid expression: Unexpected token { in ${article.image} ...

What are the best practices for incorporating jQuery animations in Angular directives?

For my website, I crafted a straightforward directive aimed at adding some basic animations to the sidebar. The animations include smooth sliding in and adjusting the width and margin of the content class. My query revolves around the suitability of emplo ...

How do I pass input values when calling an AJAX function to submit a form in HTML?

Utilizing a modal to submit new data via AJAX API consumption. Although sending the data through the API is not an issue, my lack of HTML skills makes it confusing on how to pass form data values. This scenario involves displaying a modal for users to in ...

Validate the date selected in a dropdown menu using JavaScript

I'm still relatively new to Javascript, just working my way through some tutorials. I have three select boxes in my HTML form as shown below. HTML Form: <table> <form id="enrolment" name="enrolment" onsubmit="return datevalidate();" action ...

When attempting to view the PDF file, it appears completely void

After spending countless hours on this task, I'm still not making any progress. My goal is to download a PDF file from my server while currently running the operation on localhost. However, whenever I open the downloaded PDF, all I see is a blank whit ...

Tips for achieving expansion of solely the clicked item and not the whole row

I am trying to create a card that contains a cocktail recipe. The card initially displays just the title, and when you click on a button, it should expand to show the full menu and description. The issue I'm facing is that when I click on one element, ...

"Performing validation on a number input by using the ng-change event

Im using a number input that dynamically sets the min and max values based on another form field. I have two scenarios: Level 1: Min = 2, Max = 50 Level 2: Min = 5, Max = 1000 I've set up an ng-change event on the input field to check if the entere ...

"Learn the technique of animating SVG paths with JavaScript, a step beyond traditional HTML filling

I am looking to animate SVG path elements with JavaScript instead of HTML. I have come across numerous articles discussing how to achieve this through JavaScript and jQuery by manipulating the attributes. Some helpful links I found: Fill color SVG path w ...

I'm having trouble showing data from an API in my Vue.js application using v-for

I am struggling to fetch and display data from an API in my Vue.js application. Although the API seems to be functioning correctly when I check using console.log(), I am unable to populate the table with the retrieved data. Since I am new to Vue.js, I am u ...

Why Won't My PHP Form Submit on a Bootstrap Website?

I'm struggling with validation and need some assistance. I have a Bootstrap form embedded within an HTML page and a PHP script to handle the submission. However, whenever someone clicks on Submit, the page redirects to display my PHP code instead of a ...

Manipulate a property within an array using JavaScript and AngularJS

I am working with an AngularJS model that looks like this: $scope.Model = { Users : [{ UserId: '', FirstName: '', LastName: '' }], Products :[{ ProductId: '', ...

The JSON node fails to return a value after inserting data through an ajax request

I'm encountering an issue with a jQuery plugin that loads JSON data through an AJAX call and inserts it into an existing object. When I attempt to reference the newly inserted nodes, they show up as 'undefined', despite the data appearing co ...

Issue with fullPage.js - Unable to scroll to footer on the last section of the page

I'm currently working with the fullPage.js plugin () and encountering some issues. While sliding through each section, everything functions as expected. However, when I reach the last section and try to scroll down to the footer below it, I encounter ...

Tips for inserting a page break after every item in a loop in Visualforce when generating a PDF document

I need help with rendering a VF page as PDF. The VF page iterates over a list of account records using the repeat tag. I want to apply a page break for each element in the repeat tag. The code below is working, but it has an issue - it shows an empty PDF p ...

Encountering errors with CORS middleware when attempting to make a POST request to

I've developed a CORS middleware to prevent "CORS error" for all APIs. Here's my middleware code: $response = $next($request); $response->headers->set('Access-Control-Allow-Origin', '*'); $response->headers->set(&a ...