简体   繁体   中英

Push Notifications for follow system fails after fetching FCM tokens from firestore

I'm writing a cloud function for my iOS app to watch for any follower changes in my users to notify them when someone follows them. My follower subcollection is within each user data document and I use wildcards to listen to any changes. I've also provided good logging during each step, so it's easy to see where the problem is, however, since I'm rather new to cloud functions, I don't know exactly how I'd fix it.

The cloud function is as follows.

const functions = require('firebase-functions')
const admin = require('firebase-admin')
admin.initializeApp()

let title
let body 
let payload
let FCMRegistrationToken_KEY 
exports.sendNotificationOnFollowerCreate = functions.firestore
    .document('Users/{userID}/Followers/{followerID}')
    .onCreate((snapshot, context) => {
        if(snapshot.after){
          // Get the userId and followerId
          const userID = context.params.userID;
          const followerID = context.params.followerID;
        
          // Get the data of the follower document
          const newData = snapshot.after.data()

          const fullName = newData.firstName + " " + newData.lastName 

          title = 'Someone just followed you'
          body = fullName + ' Just followed you right now!\n' + 'username: ' + newData.userName
          // Create the notification payload
          payload = {
              notification: {
                  title: title,
                  body: body
              }
          }
          // Get FMC token by fetching the FCMToken Document for the userID above. 
          admin.firestore().collection('FCMTokens').doc(userID).get().then(doc => {
              if(!doc.exists) {
                  console.log('User not found!');
              } else {
                  // Get the data of the document
                  const data = doc.data();
                  console.log(data);
                  FCMRegistrationToken_KEY = data.token 
              }
          })
          .catch(error => {
              console.log(error);
          })
          .finally(() => {
            //more code here
            // Send the notification
            admin.messaging().sendToDevice(FCMRegistrationToken_KEY, payload)
                .then(response => {
                    console.log('Notification sent successfully:', response);
                })
                .catch(error => {
                    console.log('Error sending notification:', error);
                });
            });
        }
      })

Basically when there's a new follower added, I use the userID from the context parameters to fetch the FCM token I have saved for all my users in a FCMTokens collection. After retrieving the token and creating my payload, I invoke a sendToDevice() call through admin.messaging() but it fails for some reason.

However, it fails right after that giving the following error

{
  "textPayload": "Function returned undefined, expected Promise or value",
  "insertId": "63c38ba0000e2c35c9c62c1d",
  "resource": {
    "type": "cloud_function",
    "labels": {
      "function_name": "sendNotificationOnFollowerCreate",
      "region": "us-central1",
      "project_id": "fir-eris"
    }
  },
  "timestamp": "2023-01-15T05:14:08.928821Z",
  "severity": "WARNING",
  "labels": {
    "execution_id": "no23uq1mg5a3",
    "instance_id": "00c61b117c173e48fc2cb6c3b49f2c059090e49b7252db1b187115bd42a62998c4093f283fe06ba4ec0bf7981f108fcadb527843a8c4b3c77ec1"
  },
  "logName": "projects/fir-eris/logs/cloudfunctions.googleapis.com%2Fcloud-functions",
  "trace": "projects/fir-eris/traces/e0d7dfae3ea1340e1ec101d16defc94b",
  "receiveTimestamp": "2023-01-15T05:14:09.204309551Z"
}

I'm thoroughly confused as I really don't have that much experience with cloud functions. Can someone guide me through what's happening and what could be a potential fix for this?

Thank you.

The error that you have mentioned in the question is basically seen when a function does not or has incorrectly a return statement. The code you have for cloud function does not seem to have any return statement which will have a promise return.To make sure Cloud functions knows when your code is done, you need to either return a value from the top-level function (in the case that all work happens synchronously), or return a promise from the top-level function (in the case that some work continues after the closing } of the function).
The sendNotificationOnFollowerCreate might be aborted when the trigger function finishes because it isn't waiting for that promise.
Try adding the return similar to example below:

return DeviceToken.then(result => { const token_id = result.val();  
console.log(token_id); const payload = { notification:                       
{ title: "New Job Request", body: `JobID ` + job_id, tag: collapseKey, } };                                     
return admin.messaging().sendToDevice(token_id, payload)

Also check these following examples with similar implementations:

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM