Home > database >  Firebase Cloud Functions Async
Firebase Cloud Functions Async

Time:10-14

I am making a function for firebase cloud functions, I want a function to be called every time a new document is created in "posts". I want this function to perform the tasks that I put inside the "onCeatePost" function.

The problem I have is that I'm not sure if this is the correct way to structure such a function.

In several firebase examples I have seen that it is always called return _; or return null; at the end of a task, but I don't know how to structure the function so that all the tasks are carried out, could someone help me to restructure my function or tell me what is wrong please.

There are several if statements in the function, if the created publication does not comply with them, I would like it to skip them but continue with the other tasks that I put inside the function.

I don't know if it's too much to ask, but I'm new to this language and I haven't been able to find the answer I'm looking for. Thank you!

exports.onPostCreate = functions.firestore.document("/posts/{postId}").onCreate(async (snap) => {
      const post = snap.data();
      if (post) {
        try {
          const topic = post.topic;
          const contentForFeed = post.contentForFeed;
          const uid = post.uid;
          const previous = post.prev;

          await db.collection("users").doc(uid).update({"stats.posts": admin.firestore.FieldValue.increment(1)});
    
          if (topic) {    
            await db.collection("topics").doc(topic.id).collection("user-authors").doc(uid).set({"date": snap.createTime});
          }
    
          if (contentForFeed == true) {    
            const userPath = db.collection("users").doc(uid);
            await userPath.update({"stats.lastUpdate": snap.createTime});
          }
    
          if (previous) {
            const previousId = previous.id;
            const previousUid = previous.uid;
    
            const refPrev = db.collection("posts").doc(previousId);
            await db.runTransaction(async (t) => {
              const doc = await t.get(refPrev);    
              const priority = doc.data().stats.date;
              const newDate = new admin.firestore.Timestamp(priority.seconds   120, priority.nanoseconds);
              await db.collection("posts").doc(previousId).update({"newDate": newDate});
            });
    
            if (previousUid != uid) {
              const path = db.collection("users").doc(uid).collection("user-posts");
              const dataToSet = {"timestamp": snap.createTime, "uid": uid, "postId": onReplyToPostId};
              await path(dataToSet);
            }
          }
        } catch (err) {
          functions.logger.log(err);
        }
      } else {
        return null;
      }
    });

CodePudding user response:

You'll find below the adapted code (untested) with 4 corrections.

Here are explanations for the two most important ones:

  1. (Correction 2) In a transaction you need to use the transaction's update() method and not the "standard one"
  2. (Correction 4) When all the asynchronous work is complete you need to return a value or a Promise. See this documntation page for more details.

  exports.onPostCreate = functions.firestore
    .document('/posts/{postId}')
    .onCreate(async (snap) => {
      const post = snap.data();

      if (post) {
        try {
          const topic = post.topic;
          const contentForFeed = post.contentForFeed;
          const uid = post.uid;
          const previous = post.prev;

          await db
            .collection('users')
            .doc(uid)
            .update({
              'stats.posts': admin.firestore.FieldValue.increment(1),
            });

          if (topic) {
            await db
              .collection('topics')
              .doc(topic.id)
              .collection('user-authors')
              .doc(uid)
              .set({ date: snap.createTime });
          }

          if (contentForFeed == true) {
            const userPath = db.collection('users').doc(uid);
            await userPath.update({ 'stats.lastUpdate': snap.createTime });
          }

          let previousUid;  // <= Correction 1
          if (previous) {
            const previousId = previous.id;
            previousUid = previous.uid;  // <= Correction 1

            const refPrev = db.collection('posts').doc(previousId);
            await db.runTransaction(async (t) => {
              const doc = await t.get(refPrev);
              const priority = doc.data().stats.date;
              const newDate = new admin.firestore.Timestamp(
                priority.seconds   120,
                priority.nanoseconds
              );
              t.update(refPrev, { newDate: newDate }); // <= Correction 2
            });

            if (previousUid != uid) {
              const path = db
                .collection('users')
                .doc(uid)
                .collection('user-posts');
              const dataToSet = {
                timestamp: snap.createTime,
                uid: uid,
                postId: onReplyToPostId,
              };
              await path.add(dataToSet); // <= Correction 3
            }
          }

          return null; // <= Correction 4
        } catch (err) {
          functions.logger.log(err);
        }
      } else {
        return null;
      }
    });
  • Related