0

I want to send notification to multiple devices and for that am getting the token via querying the docs and saving the token to array but it shows that array is empty. Most probably error is because am not able to add elements in the array.

My code is:-

var registrationTokens=[];

                const indexOfSender=usersList.indexOf(chatItem.senderUsername);
                let removedUsername=usersList.splice(indexOfSender,1);      //to remove the senders name from list

                usersList.forEach(async(element)=>{
                    const query = admin.firestore().collection('users').where("username","==",element);
                    const querySnapshot = await query.get();
                    if (querySnapshot.docs.length > 0) {
                        const doc = querySnapshot.docs[0];
                        const data = doc.data();
                        registrationTokens.push(data.androidNotificationToken); //adding token over here
                    }
                    else {
                        console.log("Unable to get token for the username ", element);
                    }
                });
                
                
                const message =
                {
                    notification: {
                                    title:'Message',
                                    body: body,
                                    imageUrl: url,
                                  },
                    tokens: registrationTokens,
                    data: { recipient: senderUserId },
                };

                admin.messaging().sendMulticast(message)
                .then(response =>
                {
                if (response.failureCount > 0) {
                      const failedTokens = [];
                      response.responses.forEach((resp, idx) => {
                        if (!resp.success) {
                          failedTokens.push(registrationTokens[idx]);
                        }
                      });
                      console.log('List of tokens that caused failures: ' + failedTokens);
                    }
                else
                {
                    console.log('Successfully sent messages ', response);
                }
              });

Error

Error: tokens must be a non-empty array
at FirebaseMessagingError.FirebaseError [as constructor] (/workspace/node_modules/firebase-admin/lib/utils/error.js:42:28)
at FirebaseMessagingError.PrefixedFirebaseError [as constructor] (/workspace/node_modules/firebase-admin/lib/utils/error.js:88:28)
at new FirebaseMessagingError (/workspace/node_modules/firebase-admin/lib/utils/error.js:254:16)
at Messaging.sendMulticast (/workspace/node_modules/firebase-admin/lib/messaging/messaging.js:294:19)
at sendNotificationForGroupChat (/workspace/index.js:238:35)
at exports.onCreateMessage.functions.region.firestore.document.onCreate (/workspace/index.js:116:9)
at process._tickCallback (internal/process/next_tick.js:68:7) 
lonewolf
  • 61
  • 6

2 Answers2

1

async inside forEach does not work the way you expect. If you add some logging, you will see that the loop ends before any of its async work is complete, leaving your tokens array empty before you pass it to FCM. Each iteration through the loop simply generates a promise that is not resolved. You will need to rewrite the code to actually wait for all those promises before calling FCM.

Read more about that:

Doug Stevenson
  • 297,357
  • 32
  • 422
  • 441
0

for-of loop will work just fine with asynchronous calls :)

Cheers