如何在返回新的Promise之前等待Promise解决?

时间:2019-01-01 23:47:30

标签: javascript firebase vue.js

我正在构建一个用于创建零售标牌的Web应用程序。 Firestore拥有有关标志的信息,如果用户单击“删除所有标志”,我希望能够删除所有标志。然后将出现一个对话框,要求用户确认删除数据库中的所有标志。如果它们确认,则应从Firestore中删除所有标志。

每个标志的文档ID存储在名为signIds的数组中。我希望能够遍历signIds并从Firestore的signs集合中删除每个文档。一旦所有的Promise都解决了,我想返回一个Promise并在mounted()的事件处理程序中解决它。

我尝试在代码的不同位置返回Promise,但无济于事。我也尝试使用asyncawait,但这似乎有相同的问题。

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() {
        // Get and store the document id for each sign
        database.collection("signs").get()
            .then(snapshot => {
                snapshot.forEach(doc => {
                    this.signIds.push(doc.id);
                })
            });
    },
mounted() {
        // When the user clicks 'OK' on the dialog, delete all signs from the database
        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);
            })
        }

我希望新的Promise在Firestore的Promises解决后会返回,但是目前,新的Promise在for循环完成后立即返回。

3 个答案:

答案 0 :(得分:4)

您通过signIds的{​​{1}}进行的当前迭代没有与其他任何内容相链接-Promises承诺目前不在任何地方使用。最好将每个.delete() .map到数组中的id,然后在该数组上使用Promise。如果错误由使用者处理,则无需Promise.all中的catch引发新的错误-而是仅返回Promise链,并避免使用explicit Promise construction anti-pattern

emptyQueue

如果emptyQueue() { return Promise.all( this.signIds.map(id => ( database.collection("signs").doc(id).delete() )) ); } 调用中的任何一个导致错误,则该错误将渗透到您的

.delete()
通过this.emptyQueue() // ... .catch(() => { ... }); 自动

部分。

答案 1 :(得分:1)

答案 2 :(得分:1)

您应该可以使用batch来执行此操作,并且代码应类似于以下内容:

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

for (let id of self.signIds) {
  // for each, add a delete operation to the batch
  batch.delete(database.collection("signs").doc(id));
}

// Commit the batch
batch.commit();