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

insert data into modal's interface

I'm encountering an issue with my code, where the modal is not displaying the values inside the brackets as if they were not bound correctly. Everything else in the ng-repeat seems to be working fine, but for some reason the values are not being displ ...

Using JavaScript to assign function arguments based on arbitrary object values

I am facing a challenge with a collection of arbitrary functions and a method that takes a function name along with an object or array of parameters to call the respective function. The issue arises from the varying number of inputs in these functions, som ...

Finding the index of a chosen option in Angular

Attempting to retrieve the index of the selected option from a select element using Angular. The Angular (4) and Ionic 3 frameworks are being utilized. The template structure is as follows: <ion-select [(ngModel)]="obj.city"> <ion-option ...

How can I apply an underline effect when hovering over navigation links in a responsive menu?

I've successfully added an underline effect on hover for the navigation menu. However, I encountered an issue with the responsiveness of the menu. When viewed on screens smaller than 600px, the underline effect covers the entire width of the block ins ...

Divide the division inside the box by clicking on it

I am looking to create a unique div with a random background color and a width of 100px. Additionally, I want to have a button that, when clicked, will split the original div into two equal parts, each with its own random background color. With each subs ...

Steps for embedding a font in a .pptx file

While working on creating a .pptx file using ASPOSE.Slides, I encountered some issues with embedding fonts. As an alternative option, I am looking for suggestions on how to embed custom fonts in a .pptx file using Apache POI or other methods. If you have ...

Creating a personalized <select> filter in Angular.js with two different JSON choices

I am working with a Q&A JSON feed that includes the following: "questions": [ { "answer": "Ea et non sunt dolore nulla commodo esse laborum ipsum minim non.", "id": 0, "poster": "Chelsea Vang", "question": "Ex ex elit cu ...

In order to determine if components linked from anchor elements are visible on the screen in Next.js, a thorough examination of the components

Currently, I am in the process of developing my own single-page website using Next.js and Typescript. The site consists of two sections: one (component 1) displaying my name and three anchor elements with a 'sticky' setting for easy navigation, a ...

Is it possible to locate and eliminate the apostrophe along with the preceding letter?

My objective is to tidy up a character string by removing elements that are not essential for the user and SEO, specifically the (letter before the apostrophes) in this case. I am looking for a regex solution or explanation of how to achieve this in PHP, a ...

Canceling pending asynchronous actions in React/Redux: A step-by-step guide

Imagine the scenario where a user navigates to a page and two asynchronous Redux actions are dispatched simultaneously to fetch related sets of data. If one of these fetches fails, the component will detect it and render an error component on the next cycl ...

Deciphering JSON data within AngularJS

When I retrieve JSON data in my controller using $http.get, it looks like this: $http.get('http://webapp-app4car.rhcloud.com/product/feed.json').success(function(data) The retrieved data is in JSON format and I need to access the value correspo ...

JavaScript does not recognize the $ symbol

Firebug is indicating that there is an issue with the $ variable not being defined. I have a basic index.php page that uses a php include to bring in the necessary content. The specific content causing the error is shown below: <script type="text/jav ...

Guide on adjusting shipping costs in Stripe based on the customer's address using NodeJS

Utilizing Stripe's Checkout API, I am seeking to provide international shipping options with varying costs based on the country selected at checkout. Is there a method within Checkout that allows me to dynamically adjust shipping costs based on the us ...

Show or hide text when list item is clicked

This is the rundown of services <div> <a href="#hig"><button class="tag-btn">High blood pressure Diabetes</button></a> <a href="#hih"><button class="tag-btn">High ch ...

Show an item in a visual format of a list

Need help displaying a specific object: cars: { number': 1, 'overload': 1,'brand': {'0': {'porsche': [{'price': 10, 'id': 0}],'vw': [{'price': 20, 'id': 1}] ...

Babel is failing to transpile the Modal component from material-ui-next to ES5

Issue with Babel transpiling Modal component from material-ui-next Here is my .babelrc configuration: { "presets": ["es2015", "react", "stage-1", "stage-2", "stage-3"] } This is the webpack-config.js setup: var webpack = require('webpack'); ...

Summing Up Values in Jquery Loop Through Table Rows

I am facing a challenge with a table that contains a textfield for inputting numeric values. This textfield is part of a repeated row table, with the ID 'amount'. My goal is to calculate the sum of all values entered in the textfields with the ID ...

Discovering the root cause of why a particular CSS style is not being implemented correctly

Currently, I am in the process of developing a secondary theme for one of my websites. It's going to be a dark theme. I'm facing an issue where a specific CSS style is not being applied to a particular element, even though it works perfectly fine ...

Transform the character encoding from a non-standard format to UTF-8

Imagine a scenario where there is a page with <meta charset="EUC-KR">, let's call it address-search.foo.com, that allows users to search for an address and sends the data to a specified URL by submitting an HTML form using the POST met ...

AngularJS array not refreshing following an AJAX request

Currently, I am still in the process of familiarizing myself with Angularjs and actively learning about its functionalities. One issue I have encountered is that when I define an array and loop through it using "ng-repeat," the items within ng-repeat fail ...