Как правильно получить профиль пользователя из базы данных реального времени, чтобы получить их имя пользователя до того, как вернется облачная функция? - PullRequest
0 голосов
/ 09 июня 2018

Я использую облачные функции, чтобы отправлять пользователям уведомления о том, когда происходят интересные вещи, такие как следование, лайки, комментирование.Я скопировал и адаптировал учебник 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);
          });
        });

Как я могу убедиться, что имя пользователя будет доступно до его возвращения?Спасибо.

1 Ответ

0 голосов
/ 09 июня 2018

Хорошо, я думаю, я понимаю, что вы говорите ...

Эти строки кода не делают то, что вы думаете.Все чтения БД выполняются асинхронно, поэтому ...

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

once возвращает обещание , поэтому userInfo фактически является обещанием вернуть данные.Вы не получите данные, пока не выполните then.

Больше обещаний связывания, боюсь ... просто переименуйте userInfo в userInfoPromise и добавьте их в массив Promise.All.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...