Firebase.orderByChild(). EqualTo(). Once(). Then() Promises, когда дочерний объект не существует

Конечная точка My API /auth/login принимает req.body следующим образом:

{
  "email": "[email protected]",
  "password": "supersecretpassword"
}

В конечной точке я делаю ссылку на мою базу данных Firebase (https://jacob.firebaseio.com/users). Я просматриваю данные, и когда я нахожу одного пользователя с адресом электронной почты, который соответствует req.body.email, я сравниваю пароль с тем, который хранится в базе данных.

Я следил за структурой обещаний, обозначенной в этом сообщении блога Firebase.

router.post('/login', function(req, res) {
  const ref = db.ref('/users');

  ref.orderByChild('email')
    .equalTo(req.body.email)
    .once('child_added')
    .then(function (snapshot) {
      return snapshot.val();
    })
    .then(function (usr) {

      // Do my thing, throw any errors that come up

    })
    .catch(function (err) {

      // Handle my errors with grace

      return;
    });
});

Если ни одного ребенка не найдено в ref, функция не будет продолжена (см. этот ответ). Я даже не получаю сообщение об ошибке.

Моя цель - запустить код, когда пользователь не найден с определенным адресом электронной почты (т.е. ни один ребенок не найден в ref, который удовлетворяет .equalTo(req.body.email)), но не запускает код, если пользователь найден. Ошибка не возникает, если ничего не найдено.

Я попытался добавить операторы return в стратегических точках в вызове базы данных (в конце моего .then() promises) с намерением полностью выйти из конечной точки после запуска кода. Затем я помещаю код после вызова в базу данных:

    .then(function (usr) {

      // Do my thing, throw any errors that come up

    })
    .catch(function (err) {

      // Handle my errors with grace

      return;
    });

  res.status(401)
    .json({
      error: 'No user found',
    )};

  return;
});

но этот код запускается независимо от того, выполняется ли вызов в базе данных или нет, поскольку вызов является асинхронным.

Как мне реагировать на этот вызов в базе данных, если он ничего не возвращает и по-прежнему использует Firebase promises?

Ответ 1

Событие child_added запускается только в том случае, если запрос соответствует хотя бы одному из ключей в users и будет срабатывать несколько раз, если имеется несколько совпадений.

Вместо этого вы можете использовать событие value - он будет срабатывать только один раз, и его снимок будет содержать все ключи под users, которые соответствуют или будут иметь value of null, если совпадений нет:

router.post('/login', function(req, res) {
  const ref = db.ref('/users');

  ref.orderByChild('email')
    .equalTo(req.body.email)
    .once('value')
    .then(function (snapshot) {
      var value = snapshot.val();
      if (value) {
        // value is an object containing one or more of the users that matched your email query
        // choose a user and do something with it
      } else {
        res.status(401)
          .json({
            error: 'No user found',
          )};
      }
    });
});

Что касается обработки ошибок, вы можете подключить обещание и выразить обработку ошибок следующим образом:

router.post('/login', function(req, res, next) {
  const ref = db.ref('/users');

  ref.orderByChild('email')
    .equalTo(req.body.email)
    .once('value')
    .then(function (snapshot) {
      ...
    })
    .catch(next);
});