Tips for waiting for a Promise to resolve before returning a new Promise

In the process of developing a web application tailored for crafting retail signage, I have integrated Firestore to manage pertinent information about these signs. One specific functionality I am working on is enabling users to effortlessly remove all existing signs with just one click labeled 'Remove all Signs.' Upon clicking this button, a dialog will pop up prompting the user to confirm the action of deleting all signs stored in the database. Once the confirmation is granted, the system should proceed to eradicate all signs from Firestore.

Essentially, each sign's unique document ID is contained within an array dubbed signIds. The main objective here is to efficiently iterate through this array and delete each corresponding document from the collection named signs in Firestore. Subsequently, once all deletion operations are successfully completed, I aim to return a Promise and resolve it within the event handler located in mounted().

My attempts at placing the Promise at various points within the code have proven futile thus far. Moreover, experimenting with incorporating async and await functionalities did not yield the desired outcome either.


        data() {
            return {
                signIds: [],
            }
        },
        methods: {
            showModal(message, type) {
                this.$root.$emit('openModal', {
                    closed: false,
                    text: message,
                    type: type
                })
            },
            emptyQueue() {
                let self = this;
                let deleted = 0;

                for (let id of self.signIds) {
                    database.collection("signs").doc(id).delete()
                        .then(() => {
                            console.log("Document successfully deleted!");
                            deleted++;
                        }).catch((error) => {
                            console.error("Error removing document: ", error);
                        });
                }

                // Once all signs are deleted, return new Promise
                return new Promise((resolve, reject) => {
                    return (deleted === self.signIds.length) ? resolve() : reject(new Error('An error occurred while deleting signs.'));
                });
            }      
        },
        created() {
                // Retrieve and store the document id for each sign
                database.collection("signs").get()
                    .then(snapshot => {
                        snapshot.forEach(doc => {
                            this.signIds.push(doc.id);
                        })
                    });
            },
        mounted() {
                // Trigger the deletion of all signs from the database when the user confirms.
                this.emptyQueue()
                    .then(() => {
                        setTimeout(function() {
                            self.showModal('All signs were successfully removed.', 'success');
                        }, 300);
                    }).catch(() => {
                        setTimeout(function() {
                            self.showModal('An error has occurred. Some signs were not removed.', 'error');
                        }, 300);
                    })
            }
    

The anticipated behavior is for the new Promise to only be returned after resolving Firebase's Promises; however, the current issue lies in the fact that the new Promise gets returned immediately upon completion of the for loop.

Answer №1

It seems that your current iteration process through signIds's Promises is not integrated with any other actions - the .delete() Promises are not being utilized elsewhere at this time. It would be more efficient to use .map to transform each id into a Promise within an array, and then apply Promise.all on that array. If error handling is managed in the consumer, there is no necessity to include a catch block in the function emptyQueue solely for throwing a new error - instead, simply return the Promise chain itself, avoiding the explicit Promise construction anti-pattern:

emptyQueue() {
  return Promise.all(
    this.signIds.map(id => (
      database.collection("signs").doc(id).delete()
    ))
  );
}

If any of the .delete() operations encounter an error, that error will naturally propagate up to your

this.emptyQueue()
  // ...
  .catch(() => {
    ...
  });

section via the use of Promise.all.

Answer №3

To achieve the desired outcome, you can utilize the batch method in your code snippet below:

// initialize a batch
var batch = database.batch();

for (let key of currentUser.keys) {
  // for each item, include a delete operation in the batch
  batch.delete(database.collection("items").doc(key));
}

// Execute the batch operations
batch.commit();

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

A Vue component that dynamically switches between using the router-link or href property

I'm in the process of creating a dynamic menu using the code below: <v-list-item v-for="item in items" :key="item.title" link :to="item.to"> <v-list-item-action> <v-icon>{{item.icon}}</v-icon> </v-list-item- ...

Move the last specified elements to the beginning of the array

I have an array let colorsArr = ["red", "green", "purple", "pink", "black"]; Is there a way to retrieve a specific number of elements from the END and move them to the BEGINNING of the array? Desired result: example 1: //move last 3 elements let expec ...

Do you have any suggestions on how to fix this npm SQLite installation issue?

Could use some help with an SQLite installation error I'm encountering. Any ideas on what the issue might be and how to resolve it? C:\Users\jacka\Downloads\discord-emoji-stealer-master\discord-emoji-stealer-master>npm i & ...

The 'Image' component does not have a propType defined for the native prop 'RCTImageView.overlayColor' with a native type of 'number'

Greetings, I am encountering an issue while attempting to run my react native application on Android. The app has been functioning flawlessly on iOS for several months, but this is our first endeavor at utilizing it on Android. We are using react-native .1 ...

Transformation effect when hovering over an SVG polygon as it transitions between two states

const createTransitionEffect = (navLI, startCoord, endCoord) => { const changeRate = 0.1; let currentY = startCoord; const animateChange = () => { if (currentY !== endCoord) { currentY += (endCoord - startCoord) * cha ...

Utilizing dual identifiers in a Jquery plugin

I am currently working with a jQuery plugin and I need to apply the same functionality to two different IDs. How can I achieve this? It involves a next and previous functionality where clicking on the next button automatically scrolls both divs. The issu ...

Utilizing Ajax for submitting data in a Spring application

I'm attempting to send a PUT request to the controller using AJAX. Here is my code: $().ready(function(){ $('#submit').click(function(){ var toUrl = '/users/' + $('#id').val() + '/profile'; ...

What is the proper way to access the current value of a computed property from within its own computation method?

Our goal is to activate a query when a string reaches a length of 3 characters or more, and keep it activated once triggered. Leveraging the Vue 2 Composition API, we have implemented a reactive object to manage the status of queries: import { computed, de ...

Is it possible to activate the nearby dropdown based on the user's selection?

On my html webpage, I have a form that consists of three dropdown menus each with different options: The first dropdown (A) includes choices from 1 to 6, as well as 'not set'. The second dropdown (B) allows selections from 1 to 7, and also has ...

Ways to retrieve the identifier of an iframe

document.getElementById(Iframe_id).contentWindow.addEventListener("blur", blurtest, true); This line of code assigns the blur event to an iframe and it is functioning properly. However, when in function blurtest(e) { alert(e.target.id); } An alert ...

Pass information from a child component to a parent component within a React.js application

Using the Semantic-UI CSS Framework, I have implemented a dropdown menu and want to be able to select an item from it and identify which item has been selected. While I can determine the selected item within the child component and set its state, I am faci ...

Encountering difficulties while attempting to delete with a router.delete command - receiving a 404 not

Within my application, I am passing the request parameter 'id' in the router.delete method and communicating it with the Vuex service. However, when triggering the action, an API call is made but it results in a 404 error indicating "not found" a ...

Retrieve the entity object and convert it into JSON format using json_encode

I have an array that looks something like this: $general_informations['company'] = $company_db In this array, $company_db is an Entity object with properties, such as: $city = $company_db->getCity(); After using json_encode(), I want to re ...

After successfully sending a GET request to the API, the Next.js 13.4.3 website still does not reflect new posts added on the hosting platform

I am currently using Next.js version 13.4.3 in my app directory to create a blog site. However, I am facing an issue. When I run npm run build locally on my computer and then start with npm run start, the new posts are displayed normally after adding them ...

Utilizing Angular.js to extract data from a deeply nested array of objects in JSON

Hello, I am currently learning about Angular.js and working on developing a shopping cart. In this project, I need to display an image, name, and cost of each product for multiple tenants. Each tenant has an array called listOfBinaries which contains listO ...

How to efficiently import Xlsx and csv files using AngularJS

I am looking for a way to extract data in json format from each line of xlsx and csv files using AngularJS. Currently, I am utilizing the angular-file-upload library to access the file as shown below: $scope.LatLongUploader = new FileUploader({ //url ...

Something seems to be amiss with the Vue.js eslint configuration. Can you help

I am just starting out with vueJs. I attempted to use this basic code in my vue project to update the data of a component: <template> <div> <h1> {{ message }} <h2> Hello {{ firstname }} {{ lastna ...

Methods for invoking a function from a separate .js file within React Native Expo

I'm new to using React and I've come across a challenge: In my Main.js file, there is a button: import * as React from 'react'; import { StyleSheet, Text, View, SafeAreaView, Pressable, Alert } from 'react-native'; import { M ...

The cross-domain AJAX request fails to receive a response

I am currently working on validating PAN card details. I am utilizing an AJAX call to verify the PAN card entered by the user, sending the PAN number to this URL: . The data is being sent to the following URL using AJAX call: function callbackFnc(data) { ...

The function Router.use() needs a middleware function, but instead, it received an undefined

Attempting to create an authentication app using Node.js, but encountering an error as described in the title. The code for app.js is already set up like this: var createError = require('http-errors'); var express = require('express'); ...