node.jsgoogle-cloud-platformgoogle-cloud-functionsflutter-notification

Flutter notifications from firebase messaging is delayed?


sometime the notification is delayed for no reason and then comes all together iam using https://pub.dev/packages/flutter_local_notifications https://pub.dev/packages/firebase_messaging

here is my code from cloud functions ( nodejs )

exports.messageTrigger = functions.firestore.document('/Messages/{messageID}').onCreate(

  
  async (snapshot, context) => {
    function capitalizeFirstLetter(string) {
      return string.charAt(0).toUpperCase() + string.slice(1);
    }
    var currentRoomUsers = snapshot.data().members;

    
    currentRoomUsers.forEach(  (userID) => {
        db.collection('Users').doc(userID).get().then(async(doc)=>{
        if(doc.exists && doc.id != snapshot.data().senderID){
          const message = {
           
            data: {
            
              title: `New message from ${capitalizeFirstLetter(snapshot.data().room)}`,
              body:  snapshot.data().type == 'm.text' ? 'Sent a new message' : snapshot.data().type == 'm.start'? 'Invited you for a call' : snapshot.data().type == 'm.image' ? 'Sent an image' : 'Sent a new message'
            },
            tokens: doc.data()['Device_token'],
            android: {
              priority: 'high',
            },
            priority: "high",
          }

      await admin.messaging().sendMulticast(message);
      
        }else {
          console.log("No such document!");
        }
      }).catch((error)=>{
        console.log("Error getting document:", error);
      });
    
    
    
     
    }
      
      );

 }
);

Solution

  • Firestore documents are fetched asynchronously and the sendMulticast() statement here may run before all the documents are fetched. Also, you must terminate Cloud Functions by returning a Promise. Since you are using an async function, try refactoring the code with async-await syntax as shown below:

    exports.messageTrigger = functions.firestore
      .document("/Messages/{messageID}")
      .onCreate(async (snapshot, context) => {
        try {
          function capitalizeFirstLetter(string) {
            return string.charAt(0).toUpperCase() + string.slice(1);
          }
    
          const currentRoomUsers = snapshot.data().members;
    
          // use Promise.all() to fetch all documents 
          const customRoomUsersSnap = await Promise.all(
            currentRoomUsers.map((user) =>
              db.collection("Users").doc(user).get()
            )
          );
    
          const messagePromises = [];
     
          // Iterate over all documents and add a message for every existing document
          customRoomUsersSnap.forEach((userSnap) => {
            if (userSnap.exists) {
              const message = {
                data: {
                  title: `New message from ${capitalizeFirstLetter(
                    snapshot.data().room
                  )}`,
                  body:
                    snapshot.data().type == "m.text"
                      ? "Sent a new message"
                      : snapshot.data().type == "m.start"
                      ? "Invited you for a call"
                      : snapshot.data().type == "m.image"
                      ? "Sent an image"
                      : "Sent a new message",
                },
                tokens: userSnap.data()["Device_token"],
                android: {
                  priority: "high",
                },
                priority: "high",
              };
    
              messagePromises.push(admin.messaging().sendMulticast(message));
            } else {
              console.log(`User ${userSnap.ref.id} doc does not exist`);
            }
          });
    
          // Send all messages simultaneously.
          return Promise.all(messagePromises);
        } catch (error) {
          console.log(error);
    
          // return Promise<null> in case of an error
          return null;
        }
      });