Функция Firebase asyn c метод возвращает неопределенное - PullRequest
0 голосов
/ 26 марта 2020

enter image description here

Здравствуйте, я сделал функцию Firebase, которая отслеживает совпадения пользователей. Все части работают, но я добавил еще один метод getUserDataById , где я хочу получить дополнительные данные от пользователей, он возвращает undefined . Вот что я попробовал:

exports.UserPressesLike = functions.database
  .ref('/users/{userId}/matches/{otherUserId}')
  .onCreate(async (snapshot, context) => {
    // Grab the current value of what was written to the Realtime Database.
    const original = snapshot.val();
    const userId = context.params.userId;
    const matchedUserId = context.params.otherUserId;
    const a = await checkUserMatch(userId, matchedUserId);
    if (a === true) {
      console.log('Its a match');
      addNewChat(userId, matchedUserId);
      //create chat for both users
    } else {
      console.log('There is no match');
      //do nothing
      console.log(a);
    }

    return null;
  });

checkUserMatch = async (userId, matchedUserId) => {
  const isLiked = await admin
    .database()
    .ref('/users/' + matchedUserId + '/matches/' + userId)
    .once('value')
    .then(snapshot => {
      // let tempuserId = snapshot.val();
      // if()
      let isLiked = snapshot.exists();
      console.log(isLiked);
      return isLiked;
    })
    .catch(error => {
      console.log(error);
      return snapshot;
    });
  return isLiked;
};

addNewChat = async (userId, matchedUserId) => {
  const user1 = await getUserDataById(userId);
  const user2 = await getUserDataById(matchedUserId);
  console.log(JSON.stringify('User data: ' + user1));
  const snapshot = await admin
    .database()
    .ref('/chats')
    .push({
      members: { [userId]: true, [matchedUserId]: true },
      [userId]: { username: [user1.username] },
      [matchedUserId]: { username: [user2.username] },
    });
};

getUserDataById = async userId => {
  const snapshot = await admin
    .database()
    .ref('/users/' + userId)
    .once('value')
    .then(childsnapshot => {
      let data = childsnapshot.val();
      return data;
    });
};

Но я получаю ошибку:

TypeError: Cannot read property 'username' of undefined
    at addNewChat (/srv/index.js:93:36)
    at <anonymous>
    at process._tickDomainCallback (internal/process/next_tick.js:229:7)

Проблема в методе getUserDataById. Потому что он возвращает undefined . Где я допустил ошибку?

Почему я получаю имя пользователя: {0: emilis} это должно быть имя пользователя: emilis ?? enter image description here

1 Ответ

1 голос
/ 26 марта 2020

Часть 1: getUserDataById возвращает undefined

Вы забыли return snapshot в своей функции asyn c. (Однако, поскольку это простой объект, а не снимок, я бы переименовал переменную)

getUserDataById = async userId => {
  const userData = await admin
    .database()
    .ref('/users/' + userId)
    .once('value')
    .then(childsnapshot => {
      let data = childsnapshot.val();
      return data;
    });
  return userData;
};

Однако я бы сгладил его следующим образом (что идентично приведенному выше, но кратко):

getUserDataById = userId => {
  return admin
    .database()
    .ref('/users/' + userId)
    .once('value')
    .then(childsnapshot => childsnapshot.val());
};

Часть 2. Почему мои данные, возвращаемые как {username: {0: "Emilis"}}?

{0: "Emilis"}, возвращаются как объект, а не как массив, вызвано тем, как Firebase хранит массивы в База данных в реальном времени. В блоге Firebase есть обширная статья о массивах, в которой описываются эти причуды, которые я рекомендую прочитать. Здесь я приведу основные из них.

Когда любой массив хранится в базе данных реального времени, он сохраняется в форме объекта, где {username: [user1.username] } будет храниться как {username: {0: "someusername"} }. Поскольку JSON не содержит типов, база данных реального времени больше не воспринимает эту запись как массив. Массив с несколькими записями также будет храниться как простой объект ([value1, value2] станет {0: value1, 1: value2}).

Когда Firebase JavaScript SDK загружает данные из базы данных реального времени, он проверяет ключи любые объекты для в основном последовательных чисел c последовательности (0,1,2,3, ... или 0,1,3,4, ...) и, если обнаружено, преобразует их в массив, используя null для любые пропущенные записи.

Поскольку {0: value1, 1: value2} содержит последовательные ключи 0 и 1, он будет проанализирован как [value1, value2].

Поскольку {0: "someusername"} не содержит последовательности ключей возвращается как есть.

Чтобы обойти это, удалите массив из одной записи и используйте его значение напрямую (как показано ниже) или явным образом преобразуйте его в массив в коде вашего клиента.

addNewChat = async (userId, matchedUserId) => {
  const user1 = await getUserDataById(userId);
  const user2 = await getUserDataById(matchedUserId);
  console.log(JSON.stringify('User data: ' + user1));
  return admin // don't forget to return the Promise!
    .database()
    .ref('/chats')
    .push({
      members: { [userId]: true, [matchedUserId]: true }, // FYI: these are "use value as the key" instructions not arrays.
      [userId]: { username: user1.username },
      [matchedUserId]: { username: user2.username },
    });
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...