Firebase云功能错误:提供给sendToDevice()的注册令牌必须是非空字符串或非空数组 [英] Firebase Cloud Function error: Registration token(s) provided to sendToDevice() must be a non-empty string or a non-empty array

本文介绍了Firebase云功能错误:提供给sendToDevice()的注册令牌必须是非空字符串或非空数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当在Firebase实时数据库中创建对象ConfirmedGuests时,我想向所有确认为来宾的用户发送通知.

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

因此,我首先从ConfirmedGuests对象创建一个由所有用户组成的数组.然后,我遍历所有这些用户,并将他们的deviceTokens推送到deviceTokens数组.数组allDeviceTokens应该是ConfirmedGuests中所有用户的设备令牌的数组.

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.

但是,当创建ConfirmedGuests对象时,该函数将返回错误.

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

下面是我的云功能


    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);
    });

推荐答案

您正在使用以下方法从实时数据库中加载每个用户的设备令牌:

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

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

此加载操作异步发生.这意味着,当 admin.messaging().sendToDevice(allDeviceTokens,payload)调用运行时,令牌尚未加载.

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.

要解决此问题,您需要等到所有令牌加载完毕后,再调用 sendToDevice().常见的方法是使用 Promise.all()

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);
})

这篇关于Firebase云功能错误:提供给sendToDevice()的注册令牌必须是非空字符串或非空数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆