[Vuejs]-How to turn a function into async

1đź‘Ť

âś…

You are executing several asynchronous Firebase operations in your deleteProject method (calling Firestore get(), Firestore delete(), Cloud Storage delete(), …) but you are not correctly chaining the different Promises returned by these Firebase methods.

You have to chain those Promises with the then() method , which “returns a Promise which allows for method chaining”.

So, the following should do the trick (untested however):

export const deleteProject = {
   methods: {     
      deleteProject (yearId, projectId) {
      // delete project, all documents in the images subcollection of the project, and all stored images
      return firebase.firestore().collection('years').doc(yearId).collection('projects').doc(projectId).get()
        .then((doc) => {
          // delete thumbnail
          return firebase.storage().ref(doc.data().thumbFullPath).delete()
        })
       .then(() => {
          return firebase.firestore().collection('years').doc(yearId).collection('projects').doc(projectId).delete();
       })
       .then(() => {
          return firebase.firestore().collection('years').doc(yearId).collection('projects').doc(projectId).collection('images').get()
       })
       .then((querySnapshot) => {
          const promises = [];
          querySnapshot.forEach((doc) => {
            // delete gallery image
            this.imagePaths.append(doc.data().fullPath)
            // delete reference document for gallery image
            promises.push(doc.ref.delete());
          })
          return Promise.all(promises);
       })
      }
  }
}

And since this deleteProject() method is now asynchronous, you need to call it as follows in your mixin:

  methods: {
    del () {
      // call deleteYear method from mixin
      this.deleteProject(this.yearId, this.projectId)
      .then(() => {
         // emit reload signal for database relaod
         this.$emit('reload')
         // close modal
         this.dialog = false
      })
    }
  }

Note that we use Promise.all() to execute in parallel all the delete() method calls in the forEach(). Promise.all() method returns a single Promise that fulfills when all of the promises passed to as an iterable (i.e. the promises array) have been fulfilled.

👤Renaud Tarnec

2đź‘Ť

You simply need to return the foremost .then() in the Promise chain of this deleteProject method, and any subsequent call should be able to pick it up from this point.

deleteProject() {
  // Add a return keyword here, or assign the Promise to a variable and return it. 
  return firebase.firestore().collection('years').doc(yearId).collection('projects').doc(projectId).get()
        .then( /* removed for brevity */ )
}

The calling method,

methods: {
  del() {
    this.deleteProject(this.yearId, this.projectId).then(() => {
      this.$emit('reload')
    })
  }
}

Or, make it “prettier” with the async keyword,

methods: {
  async del() {
    // You probably want to do try-catch here as well.
    await this.deleteProject(this.yearId, this.projectId);

    this.$emit('reload');
  }
}
👤Yom T.

Leave a comment