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?
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.
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.
orderByChild - This method sorts the data according to specified sub-collection or child path. orderByKey - Performs sorting according to the specified key value.
A DataSnapshot instance contains data from a Firebase Database location. Any time you read Database data, you receive the data as a DataSnapshot.
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);
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With