Firebase Cloud Function error: Registration token(s) provided to sendToDevice() must be a non-empty string or a non-empty array

北慕城南 提交于 2021-01-29 09:29:31

问题


I want to send a notification to all users who are confirmed guests when the object confirmedGuests is created in the Firebase Realtime Database.

So, I first create an array of all the users from confirmedGuests object. Then, I iterate through all these users and push their deviceTokens to an array of deviceTokens. The array allDeviceTokens is expected to be the array of device tokens of all users in confirmedGuests.

However, when confirmedGuests object is created, the function returns an error.

Below is my cloud function


    exports.sendNotification = functions.database
    .ref('/feed/{pushId}/confirmedGuests')
    .onCreate((snapshot, context) => {
        const pushId = context.params.pushId;
        if (!pushId) {
            return console.log('missing mandatory params for sending push.')
        }
        let allDeviceTokens = []
        let guestIds = []
        const payload = {
            notification: {
                title: 'Your request has been confirmed!',
                body: `Tap to open`
            },
            data: {
                taskId: pushId,
                notifType: 'OPEN_DETAILS', // To tell the app what kind of notification this is.
            }
        };
          let confGuestsData = snapshot.val();
          let confGuestItems = Object.keys(confGuestsData).map(function(key) {
              return confGuestsData[key];
          });
          confGuestItems.map(guest => {
            guestIds.push(guest.id)
          })
          for(let i=0; i<guestIds.length; i++){
            let userId = guestIds[i]
            admin.database().ref(`/users/${userId}/deviceTokens`).once('value', (tokenSnapshot) => {
              let userData = tokenSnapshot.val();
              let userItem = Object.keys(userData).map(function(key) {
                  return userData[key];
              });
              userItem.map(item => allDeviceTokens.push(item))
            })
          }
          return admin.messaging().sendToDevice(allDeviceTokens, payload);
    });


回答1:


You're loading each user's device tokens from the realtime database with:

admin.database().ref(`/users/${userId}/deviceTokens`).once('value', (tokenSnapshot) => {

This load operation happens asynchronously. This means that by the time the admin.messaging().sendToDevice(allDeviceTokens, payload) calls runs, the tokens haven't been loaded yet.

To fix this you'll need to wait until all tokens have loaded, before calling sendToDevice(). The common approach for this is to use Promise.all()

let promises = [];
for(let i=0; i<guestIds.length; i++){
  let userId = guestIds[i]
  let promise = admin.database().ref(`/users/${userId}/deviceTokens`).once('value', (tokenSnapshot) => {
    let userData = tokenSnapshot.val();
    let userItem = Object.keys(userData).map(function(key) {
      return userData[key];
    });
    userItem.map(item => allDeviceTokens.push(item))
    return true;
  })
  promises.push(promise);
}
return Promise.all(promises).then(() => {
  return admin.messaging().sendToDevice(allDeviceTokens, payload);
})


来源:https://stackoverflow.com/questions/55980664/firebase-cloud-function-error-registration-tokens-provided-to-sendtodevice

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!