How do i return a promise and object from firebase functions?

Viewed 159

Just a heads up, this my first day using cloud functions. I have a cloud function that returns an object to my client after verifying some details. I also want to use this function to write to my firestore database. But to write to my database i have to return a promise from my function. How do i do both and make this work? Here's my code.

export const verifyDetails = functions.https.onCall(async (data, context) => {

    const chosenUsername = data.username;
    const chosenEmail = data.email;

    const allEmails: string[] = [];
    const allUsernames: string[] = [];

    let usernameExists = false;
    let emailExists = false;

    await admin.firestore().collection('Users').get()
        .then((snapshot) => {
            snapshot.forEach((doc) => {
                allEmails.push(doc.data().email);
                allUsernames.push(doc.data().username);
            })

            allEmails.forEach((email) => {
                if (email === chosenEmail) {
                    emailExists = true;
                }
            });

            allUsernames.forEach((username) => {
                if (username === chosenUsername) {
                    usernameExists = true;
                }
            });

            if (!usernameExists && !emailExists) {
                registerDetails(chosenUsername, chosenEmail);
            }

        })
        .catch((error) => {
            console.log('Error retrieving firestore documents', error);
        });

    return { usernameExists: usernameExists, emailExists: emailExists };

});


export const registerDetails = functions.https.onCall(async (data, context) => {
    return admin.firestore().collection('Users').add({
        email: data.chosenEmail,
        username: data.chosenUsername
    });
});

I tried using another https callback function and call it within the main function. This doesn't write to my database but it does return my object. Please help!

1 Answers

Factor out the contents of the registerDetails function so both onCall functions can use it...

async function addUser(data) {
  return admin.firestore().collection('Users').add({
    email: data.chosenEmail,
    username: data.chosenUsername
  })
}

Now verifyDetails can use it like this...

export const verifyDetails = functions.https.onCall(async (data, context) => {
  let querySnapshot = await admin.firestore().collection('Users').get()
  // code from the OP here.
  // because we used await, the code doesn't have to be in a then block
  
  await addUser({ chosenEmail, chosenUsername })
  return { usernameExists: usernameExists, emailExists: emailExists };
})

and registerDetails can use it like this...

export const registerDetails = functions.https.onCall(async (data, context) => {
  return addUser(data)
})

Note that verifyDetails doesn't return a promise, but it awaits the async work, which also works.

Related