snibbo
snibbo

Reputation: 189

Wait for multiple Promises in Firebase Functions

I try to figure out how I can wait for several promises to be executed before the function ends.

Essentially, this is what I try to do:

Here is what I tried so far:

A) Main function (starts the first level of promises):

export function cleanUpAllData(user) {
  const userId = user.uid;
  const promises = [];
  promises.push(deleteCategoriesData(userId)); // this works fine
  promises.push(deleteUserAndGroupData(userId)); // this one has other promises which still run when Promise.all() is finished
  Promise.all(promises)
    .then(() => {
      return "ok"; // this works so far, but not all promises are resolved
    })
    .catch(errPromises => {
      console.log("an error occured during the processing of main promises");
      console.log(errPromises, errPromises.code);
      return "error";
    })
}

B) deleteUserAndGroupData function (the other promise is working fine): each group found in the user data starts another level of promises and also triggers a thrid level of promises (deleteGroup) - the rest is working fine

function deleteUserAndGroupData(userId) {
  const promisesUserData = [];

  return admin.firestore().collection('users').doc(userId).collection('groups').get()
    .then(userGroups => {
        userGroups.forEach(userGroupData => {
            // delete group data
            promisesUserData.push(deleteGroups(userId, userGroupData.id)); // here are other promises that need to be resolved - somewhere is a problem              
            // delete all Groups in Users (subcollection)
            promisesUserData.push(deleteGroupInUser(userId, userGroupData.id)); // this works fine          
        });
        Promise.all(promisesUserData)
        .then(() => {
            admin.firestore().collection('users').doc(userId).delete()
                .then(() => {
                    return "user data deleted"; // works fine
                })
                .catch(() => {
                    console.log("an error occured during deleting of user");
                    return "error";
                });
        })
        .catch(errPromises => {
            console.log("an error occured during the processing of promisesUserData");
            console.log(errPromises, errPromises.code);
            return "error";
        })
    })
    .catch(errUserGroups => {
        console.log(errUserGroups, errUserGroups.code);
        return "no groups in User";
    });
}

C) deleteGroups functions: deletes the sub collections in the group (works fine) and after that the group shall be deleted if there is no other user (which does not work)

function deleteGroups(userId,groupId) {
  const promisesDeleteGroups = [];
  // delete groups subcollection data 
  promisesDeleteGroups.push(deleteGroupRole(userId, groupId));
  promisesDeleteGroups.push(deleteGroupUser(userId, groupId));

  return Promise.all(promisesDeleteGroups).then(() => {
    checkForOthers(groupId);
  }).catch(errDeleteGroupSubcollections => {
    console.log("an error occured during the processing of promisesDeleteGroups");
    console.log(errDeleteGroupSubcollections, errDeleteGroupSubcollections.code);
    return "error";
  });
}

D) checkForOthers function - checks if there is any entry in the subcollection and shall start to delete the group (but does not)

function checkForOthers(groupId) {
  return admin.firestore().collection('groups').doc(groupId).collection('users').get()
    .then(groupUsers => {
        return "other users exist - group should not be deleted";
    })
    .catch(errGroupUsers => {
        // console.log("no other group members - group can be deleted");
        // return "no other group members - group can be deleted";
        console.log(errGroupUsers, errGroupUsers.code);
        checkForInvitesAndDelete(groupId);
    });;
}

E) checkForInvitesAndDelete: first I want to delete another subcollection which might or might not exists, if another user has been invited to the group; then it should trigger the final group delete (which seems not to work)

function checkForInvitesAndDelete(groupId) {
  const promisesInvitesAndDelete = [];
  return admin.firestore().collection('groups').doc(groupId).collection('invitations').get()
    .then(groupInvitations => {
        console.log("delete open Group Invitations");
        groupInvitations.forEach(groupInvite => {
            promisesInvitesAndDelete.push(deleteGroupInvite(groupId, groupInvite.id));
        });
        Promise.all(promisesInvitesAndDelete)
            .then(() => {
                deleteGroup(groupId)
            })
            .catch(errPromisesInvitesAndDelete => {
                console.log("an error occured during the processing of deleting group invites");
                console.log(errPromisesInvitesAndDelete, errPromisesInvitesAndDelete.code);
                return "error";
            });
    })
    .catch(() => {
        console.log("no open invitations");
        deleteGroup(groupId);
    });
}

F) deleteGroup function

function deleteGroup(groupId) {
  return admin.firestore().collection('groups').doc(groupId).delete();
}

I am relatively new to programming, especially Firebase Functions, so any help would be appreciated!!

Thank you!

Upvotes: 4

Views: 1817

Answers (2)

snibbo
snibbo

Reputation: 189

I added the 'return' statements which helped a lot, but that was not the full answer.

In (D) I thought that if my collection has no data, it would run into the 'catch' phase, but it is not. So, I needed to check for an empty result set in my 'then' phase.

if (groupUsers.empty) {
  return checkForInvitesAndDelete(groupId);
} else {
  return "other users exist - group should not be deleted";
} 

Same with the function (E) when there is no open invitation.

Upvotes: 0

J. Doe
J. Doe

Reputation: 13103

You are not using the return keyword everywhere, where it should be. If you do a async task, you must 'return' it someway.

Some examples:

example A: add return before Promise.all(promises)

... B: add return before Promise.all(promisesUserData)

... C: add return before checkForOthers(groupId)

... D: add return before checkForInvitesAndDelete(groupId)

... E: add return before Promise.all(promisesInvitesAndDelete) and deleteGroup(groupId)

Upvotes: 5

Related Questions