David Henry
David Henry

Reputation: 3046

Return multiple Promises (Firebase Cloud Functions)

I have a Firebase Cloud function that adds a newly authenticated user into the Firestore Database.

Current Function

exports.createUserAccount = functions.auth.user().onCreate((user) => {
    const uid = user.uid;
    const privateUserInfoRef = admin.firestore().doc(`/privateUserInfo/${uid}`);
    return privateUserInfoRef.set({
        isAnonymous: true,
        avgRating: 0,
        numRatings: 0,
        loggedInAt: Date.now()
    });
});

However, I'd like to return another promise after return privateUserInfoRef.set({ has completed.

I'd like to shift the avgRating & numRatings and set it on admin.firestore().doc('/publicUserInfo/${uid}'); instead.

Upvotes: 3

Views: 1325

Answers (2)

Doug Stevenson
Doug Stevenson

Reputation: 317322

Try this:

return privateUserInfoRef.set({
    isAnonymous: true,
    avgRating: 0,
    numRatings: 0,
    loggedInAt: Date.now()
})
.then(() => {
    return admin.firestore().doc(...).update(...);
});

then returns a promise that will propagate up to the return statement. Keep chaining then blocks to do more async work. Cloud Functions will wait until the entire chain is done. This is basic promise handling in JavaScript (but it gets easier with async/await syntax).

I strongly suggest learning extensively about JavaScript promises work in order to make effective use of Cloud Functions on nodejs. It will save you a lot of time in the future.

Upvotes: 2

Frank van Puffelen
Frank van Puffelen

Reputation: 598668

If you want to run multiple operations, once after the other, and return the result of the final one (or the first one that fails), you can chain the then() clauses:

return privateUserInfoRef.set({
  isAnonymous: true,
  avgRating: 0,
  numRatings: 0,
  loggedInAt: Date.now()
}).then((resultOfSet) => {
  return anotherRef.set(...); 
});

You can repeat this chain for as long as needed.


If you have multiple operations that can run in parallel, you can alternatively use Promise.all() to return the combined result of all of them:

return Promise.all([
    privateUserInfoRef.set(...)
    anotherRef.set(...)
]);

The return value will be an array with the results of the individual set() operations.


I'm just using set() operations as an example here. This pattern applies to any call that returns a promise, including (for the Realtime Database) once() and push(), but also for non-Firebase operations that return promises.

Upvotes: 3

Related Questions