web-dev-qa-db-fra.com

Firebase .orderByChild (). EqualTo (). Once (). Then () Promet quand l'enfant n'existe pas

Mon point de terminaison API /auth/login Prend un req.body Comme ceci:

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

Au point final, je fais référence à ma base de données Firebase (https://jacob.firebaseio.com/users). Je recherche dans les données et lorsque je trouve un utilisateur avec l'e-mail qui correspond à req.body.email, Je compare le mot de passe avec celui stocké dans la base de données.

J'ai suivi la structure de promesse décrite dans ce billet de blog 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;
    });
});

Si aucun enfant n'est trouvé dans ref, la fonction ne fonctionne pas (voir cette réponse ). Je ne reçois même pas d'erreur.

Mon objectif est d'exécuter du code quand aucun utilisateur n'est trouvé avec un certain e-mail (c'est-à-dire qu'aucun enfant n'est trouvé dans ref qui satisfait .equalTo(req.body.email)), mais pas d'exécuter le code si un utilisateur est trouvé. Aucune erreur n'est lancée lorsque rien n'est trouvé.

J'ai essayé d'ajouter des instructions return à des points stratégiques de l'appel à la base de données (à la fin de mes promesses .then()) avec l'intention de sortir complètement du point de terminaison après l'exécution du code. J'ai ensuite mis du code après l'appel à la base de données:

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

mais ce code est exécuté que l'appel à la base de données réussisse ou non, car l'appel est asynchrone.

Comment puis-je réagir à cet appel à la base de données si elle ne renvoie rien et utilise toujours les promesses Firebase?

13
Jacob

Le child_added L'événement ne se déclenche que si la requête correspond à au moins une des clés sous users et se déclenche plusieurs fois s'il existe plusieurs correspondances.

Vous pouvez utiliser à la place l'événement value - il ne se déclenchera qu'une seule fois et son instantané contiendra toutes les clés sous users qui correspondront ou auront value de null s'il n'y a pas de correspondance:

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

En ce qui concerne la gestion des erreurs, vous pouvez câbler la promesse et exprimer la gestion des erreurs comme ceci:

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