Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Firebase .orderByChild().equalTo().once().then() Promises when child doesn't exist

My API /auth/login endpoint takes a req.body like this:

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

At the endpoint, I make a reference to my Firebase database (https://jacob.firebaseio.com/users). I search through the data, and when I find one user with the email that matches req.body.email, I compare the password with the one stored in the database.

I followed the promise structure outlined in this Firebase blog post.

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

If no child is found at ref, the function does not proceed (see this answer). I don't even get an error thrown.

My goal is to run code when no user is found with a certain email (i.e. no child is found at ref that satisfies .equalTo(req.body.email)), but not run the code if a user is found. No error is thrown when nothing is found.

I tried adding return statements at strategic points in the call to the database (at the end of my .then() promises) with the intention of breaking out of the endpoint entirely after the code was run. I then put code after the call to the database:

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

but this code is run whether the call to the database succeeds or not, since the call is asynchronous.

How do I react to this call to the database if it doesn't return anything and still use Firebase promises?

like image 942
Jacob Avatar asked Aug 26 '16 23:08

Jacob


People also ask

What is orderByChild in firebase?

Firebase orderByChild once child_added is only giving one child. 0. Returning a single child's value on Firebase query using orderByChild and equalTo. 3. unspecified index when searching data with firebase cloud function on nested object running nested Query.

How to retrieve data from Realtime database in Firebase?

Asynchronous listeners: Data stored in a Firebase Realtime Database is retrieved by attaching an asynchronous listener to a database reference. The listener is triggered once for the initial state of the data and again anytime the data changes. An event listener may receive several different types of events.

What is orderByChild Android?

orderByChild - This method sorts the data according to specified sub-collection or child path. orderByKey - Performs sorting according to the specified key value.

What is snapshot in firebase?

A DataSnapshot instance contains data from a Firebase Database location. Any time you read Database data, you receive the data as a DataSnapshot.


1 Answers

The child_added event only fires if the query matches at least one of the keys under users and will fire multiple times if there are multiple matches.

You can use the value event instead - it will fire only once and its snapshot will contain all of the keys under users that matched or will have value of null if there are no matches:

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

Regarding handling of errors, you can wire up the promise and express error handling like this:

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);
});
like image 168
cartant Avatar answered Sep 17 '22 01:09

cartant