Firebase 在云函数返回之前,如何正确地从实时数据库获取用户配置文件以获取他们的用户名?

Firebase 在云函数返回之前,如何正确地从实时数据库获取用户配置文件以获取他们的用户名?,firebase,firebase-realtime-database,google-cloud-functions,Firebase,Firebase Realtime Database,Google Cloud Functions,我正在实现云功能,以便在有趣的事情发生时(如跟踪、喜欢、评论)向用户发送通知。我复制并改编了Firebase教程,以便在检测到关注者节点的更改时发送通知,但我还需要查询数据库以获取关注者的帐户数据,包括他们的用户名。我想我已经很接近了,但是函数没有及时完成,我很难理解承诺。以下是函数: exports.sendFollowerNotification = functions.database.ref(`/userFollowers/{followedUid}/{followerUid}`

我正在实现云功能,以便在有趣的事情发生时(如跟踪、喜欢、评论)向用户发送通知。我复制并改编了Firebase教程,以便在检测到关注者节点的更改时发送通知,但我还需要查询数据库以获取关注者的帐户数据,包括他们的用户名。我想我已经很接近了,但是函数没有及时完成,我很难理解承诺。以下是函数:

    exports.sendFollowerNotification = functions.database.ref(`/userFollowers/{followedUid}/{followerUid}`)
        .onWrite((change, context) => {
          const followerUid = context.params.followerUid;
          const followedUid = context.params.followedUid;
          // If un-follow we exit the function

          if (!change.after.val()) {
            return console.log('User ', followerUid, 'un-followed user', followedUid);
          }
          console.log('We have a new follower UID:', followerUid, 'for user:', followedUid);

          // Get the list of device notification tokens.
          const getDeviceTokensPromise = admin.database()
              .ref(`/users/${followedUid}/notificationTokens`).once('value');
              console.log('Found the followed user\'s token')

          const userInfo = admin.database().ref(`/users/${followedUid}`).once('value');
          console.log(userInfo)
          const username = userInfo['username'];
          console.log(username);

////////////////// ABOVE is where I'm trying to get the username by reading their account data ///////////////////

          // Get the follower profile.
          const getFollowerProfilePromise = admin.auth().getUser(followerUid);

          // The snapshot to the user's tokens.
          let tokensSnapshot;

          // The array containing all the user's tokens.
          let tokens;

          return Promise.all([getDeviceTokensPromise, getFollowerProfilePromise]).then(results => {
            tokensSnapshot = results[0];
            const follower = results[1];

            // Check if there are any device tokens.
            if (!tokensSnapshot.hasChildren()) {
              return console.log('There are no notification tokens to send to.');
            }
            console.log('There are', tokensSnapshot.numChildren(), 'tokens to send notifications to.');
            console.log('Fetched follower profile', follower);

            // Notification details.
            const payload = {
              notification: {
                title: 'You have a new follower!',
                body: `{username} is now following you.`,
              }
            };

            // Listing all tokens as an array.
            tokens = Object.keys(tokensSnapshot.val());
            // Send notifications to all tokens.
            return admin.messaging().sendToDevice(tokens, payload);
          }).then((response) => {
            // For each message check if there was an error.
            const tokensToRemove = [];
            response.results.forEach((result, index) => {
              const error = result.error;
              if (error) {
                console.error('Failure sending notification to', tokens[index], error);
                // Cleanup the tokens who are not registered anymore.
                if (error.code === 'messaging/invalid-registration-token' ||
                    error.code === 'messaging/registration-token-not-registered') {
                  tokensToRemove.push(tokensSnapshot.ref.child(tokens[index]).remove());
                }
              }
            });
            return Promise.all(tokensToRemove);
          });
        });

如何确保用户名在返回之前可用?谢谢。

好的,我想我明白你的意思了

这些代码行不符合您的想法。所有数据库读取都是异步完成的,因此

const userInfo = admin.database().ref(`/users/${followedUid}`).once('value');
console.log(userInfo)
const username = userInfo['username'];
console.log(username);
,因此,
userInfo
实际上是一种返回数据的承诺。在执行
之后的
操作之前,您将无法获取数据


我担心会有更多的连锁承诺。。。只需将
userInfo
重命名为
userInfoPromise
,并将其添加到您的
承诺中。所有
数组。

好的,我想我明白您的意思了

这些代码行不符合您的想法。所有数据库读取都是异步完成的,因此

const userInfo = admin.database().ref(`/users/${followedUid}`).once('value');
console.log(userInfo)
const username = userInfo['username'];
console.log(username);
,因此,
userInfo
实际上是一种返回数据的承诺。在执行
之后的
操作之前,您将无法获取数据


我担心会有更多的连锁承诺。。。只需将
userInfo
重命名为
userInfoPromise
,并将其添加到您的
Promise.All
数组中。

好吧,在云函数返回之前,您不需要做任何事情。这里有一个有趣的功能视频。基本上,您正在将一个函数传递到promise中,以便在检索datasnapshot时执行。在运行您发送的代码之前,All将等待所有承诺完成。这都是异步的。考虑到这一点,看起来您正在尝试编排大量代码来完成。也许有一种更好的方法来构造调用/DB,以避免大部分调用?自由层具有合理的执行限制。有一些很棒的视频。也许可以通过观看视频来了解如何展平你的身体DB@JamesPoag这段视频有助于我的理解。不过,该功能是直接从Firebase复制而来的——我确信它的设计有点过度,尤其是在日志记录方面。我也是付费的!你在付费层,而它正在超时?天哪,那就像是几秒钟?也许这不是超时?这不是超时!读取/user/uid值不会在函数的其余部分之前返回,因此用户名永远不可用。我试图理解如何确保它在函数的其余部分之前返回,从而使其可用。好吧,在云函数返回之前,您实际上不需要做任何事情。这里有一个有趣的功能视频。基本上,您正在将一个函数传递到promise中,以便在检索datasnapshot时执行。在运行您发送的代码之前,All将等待所有承诺完成。这都是异步的。考虑到这一点,看起来您正在尝试编排大量代码来完成。也许有一种更好的方法来构造调用/DB,以避免大部分调用?自由层具有合理的执行限制。有一些很棒的视频。也许可以通过观看视频来了解如何展平你的身体DB@JamesPoag这段视频有助于我的理解。不过,该功能是直接从Firebase复制而来的——我确信它的设计有点过度,尤其是在日志记录方面。我也是付费的!你在付费层,而它正在超时?天哪,那就像是几秒钟?也许这不是超时?这不是超时!读取/user/uid值不会在函数的其余部分之前返回,因此用户名永远不可用。我试图理解如何确保它在函数的其余部分之前返回,从而使它可用。