This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 5 years ago.
I am pulling data from Firebase. I want to extract values and save them in the array. After that I will use that array values as strings in my application. The problem is when I push values from DB to array, it adds undefined at the end of the array. And when I want to see the value of array (carUserDetails[0]) it returns undefined, but should return a string "BMW"
var UserID = firebase.auth().currentUser.uid;
var refModels = firebase.database().ref("/users/" + UserID);
var carUserDetails = [];
refModels.once('value').then(function (snapshot) {
snapshot.forEach(function (childSnapshot) {
var usersValue = childSnapshot.val(); //get the values of the object
carUserDetails.push(
usersValue.carMake,
usersValue.carYear,
usersValue.carModel,
usersValue.carTrim
);
});
});
console.log(carUserDetails);
console.log(carUserDetails[0]) // returns undefined too
So what could be the problem
So yes it an asynchronous call issue. See the fix
var UserID = firebase.auth().currentUser.uid;
var refModels = firebase.database().ref("/users/" + UserID);
var carUserDetails = [];
refModels.once('value').then(function (snapshot) {
snapshot.forEach(function (childSnapshot) {
var usersValue = childSnapshot.val(); //get the values of the object
carUserDetails.push(
usersValue.carMake,
usersValue.carYear,
usersValue.carModel,
usersValue.carTrim
);
});
$scope.getValueFromArray(); //call function here
});
$scope.getValueFromArray = function(){
console.log(carUserDetails[0]); returns "BMW"
}
I think it's because you are too early calling console.log remember reading firebase value is asynchronous. You should put your console, inside function (snapshot) and after snapshot.forEach
refModels.once('value').then(function (snapshot) {
snapshot.forEach(function (childSnapshot) {
....
});
console.log(carUserDetails);
});
Related
My Firebase data base contains JSON objects, each with the same parameters as seen below. Firebase data
I want to get an array that has each objects country. So if I have 4,000 objects I want to get an array of 4,000 strings all containing a country.
Right now I can get the console to log all the 4,000 objects into an array using the code below.
componentWillMount() {
this.fetchData();
}
fetchData = async () => {
var data1 = [];
var fireBaseResponse = firebase.database().ref();
fireBaseResponse.once('value').then(snapshot => {
snapshot.forEach(item => {
var temp = item.val();
data1.push(temp);
return false;
});
console.log(data1);
});
}
But when I try doing
var fireBaseResponse = firebase.database().ref().child('country');
I get an array of nothing.
Any help would be great.
As mentioned in the comments, you can create a new temp object containing just country before pushing it into your array.
snapshot.forEach(item => {
var temp = { country: item.val().country };
data1.push(temp);
return false;
});
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 5 years ago.
I am trying to implement nested api calls in ionic3
submitLoginForm() {
var username = this.formData.value.username;
var password = this.formData.value.password;
var bodyjson;
var userId;
this.ApidataService.logincheck(username,password).subscribe(data => {
this.logindetail = data;
bodyjson = JSON.parse(this.logindetail._body);
userId = bodyjson.user.id;
if( userId != undefined){
this.ApidataService.userdata(userId).subscribe(data => {
this.userInfo = data;
});
}
console.log(userId);
});
console.log(this.userInfo);
}
Now when I call this function the nested api returns undefined for the first call and then from the second call onwards it returns proper values however when I try to log the argument that is being sent to the api I notice that the correct value is passed each time. I believe that this is due to some synchronization issues but am unable to figure out the issue and the solution for the same.
You can use flatMap here.It seems you don't need to retrieve results of both requests hence this should work for you.
import { Observable } from "rxjs/Observable";
import 'rxjs/add/observable/flatMap';
Then:
this.ApidataService.logincheck(username,password).flatMap(
(data) => {
this.logindetail = data;
bodyjson = JSON.parse(this.logindetail._body);
userId = bodyjson.user.id;
if( userId != undefined){
return this.ApidataService.userdata(userId);
}else{
return Observable.empty();
}
}).map((res: Response) => res ? res.json() : {})
.subscribe(data => {
this.userInfo = data ? data : {};
});
You can read more about flatMap here
I'm able to query my users array with an e-mail address and return the user's account info:
users.orderByChild('email').equalTo(authData.user.email).once('value').then(function(snapshot) {
console.log(snapshot.val());
console.log(snapshot.key); // 'users'
console.log(snapshot.child('email').key); 'email'
...
How do I get the key (-KiBBDaj4fBDRmSS3j0r). snapshot.key returns users. snapshot.child('email').key returns email. The key doesn't appear to be a child, i.e., it appears to be in between users and email.
You could do something like this:
var key = Object.keys(snapshot.val())[0];
Ref: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
The Object.keys() method returns an array of a given object's own
enumerable properties, in the same order as that provided by a
for...in loop (the difference being that a for-in loop enumerates
properties in the prototype chain as well).
Realtime database:
For this you can simple use: snapshot.key
snapshot = firebase.database.DataSnapshot
this.app.database()
.ref('/data/')
.on('value', function(snapshot) {
const id = snapshot.key;
//----------OR----------//
const data = snapshot.val() || null;
if (data) {
const id = Object.keys(data)[0];
}
});
Firestore:
snapshot.id
snapshot = firebase.firestore.DocumentSnapshot
this.app.firestore()
.collection('collection')
.doc('document')
.onSnapshot(function(snapshot) {
const id = snapshot.id;
//----------OR----------//
const data = snapshot.data() || null;
if (data) {
const id = Object.keys(data)[0];
}
});
users.orderByChild('email').equalTo(authData.user.email) is a Query (doc) that you have built by "chaining together one or more of the filter methods". What is a bit specific with your query is that it returns a dataSnapshot with only one child, since you query with equalTo(authData.user.email).
As explained here, in this exact case, you should loop over the returned dataSnapshot with forEach():
Attaching a value observer to a list of data will return the entire list of data as a single snapshot which you can then loop over to access individual children.
Even when there is only a single match for the query, the snapshot is
still a list; it just contains a single item. To access the item,
you need to loop over the result, as follows:
ref.once('value', function(snapshot) {
snapshot.forEach(function(childSnapshot) {
var childKey = childSnapshot.key;
var childData = childSnapshot.val();
// ...
});
});
Similar to camden_kid, I used Object.keys(arr), but in three lines:
var arr = snapshot.val();
var arr2 = Object.keys(arr);
var key = arr2[0];
console.log(key) // -KiBBDaj4fBDRmSS3j0r
I found new way to get the data based on snapshot key -
firebase.database().ref('events').once('value',(data)=>{
//console.log(data.toJSON());
data.forEach(function(snapshot){
var newPost = snapshot.val();
console.log("description: " + newPost.description);
console.log("interest: " + newPost.interest);
console.log("players: " + newPost.players);
console.log("uid: " + newPost.uid);
console.log("when: " + newPost.when);
console.log("where: " + newPost.where);
})
})
I'm working with Firebase realtime database and I want to retrieve an array data:
Data:
And my function:
function traerUsuarios(firebase)
{
var ref = firebase.database().ref().child('/Usuario');
console.log(ref)
ref.once('value', function (snap) {
snap.forEach(function (item) {
var itemVal = item.val();
console.log(itemVal);
});
});
}
But the result:
Show me object but no de for of the items
What im doing wrong?
Each item in your for loop are the children of Usario. Each of these children (from your picture 056BN.., CQL.., and E4ll) have an object as their value (hence why they have a + next to them in the database).
So when you say item.val() you're getting the value of each one of those children, which is their corresponding object (The data you see when you click the + in the database.
Thanks to #MarksCode , I fixed the function with data refs:
function traerUsuarios(firebase) { var key;
var starCountRef;
var usuarios=new Array();
// var ref = firebase.database().ref().child('/Usuario');
var query = firebase.database().ref("/Usuario").orderByKey();
query.once("value")
.then(function (snapshot) {
snapshot.forEach(function (childSnapshot) {
// key will be "ada" the first time and "alan" the second time
key = childSnapshot.key;
starCountRef = firebase.database().ref("/Usuario/"+key);
starCountRef.on('value', function (snapshot) {
console.log(snapshot.val());
usuarios.push([key,snapshot.val()]);
});
});
}); }
And the result show me the values:
Facing problem to get array list which is push under forEach operation cant be access by out of forEach. I unable to get the array value(instaprofile) after forEach operation
var uid = 132456;
var instaprofile = [];
var ref = firebase.database().ref("InstaAccounts");
ref.orderByChild("IgrowthId").equalTo(uid).once("value")
.then(function (snapshot) {
snapshot.forEach(function (childsnap) {
var igid = parseInt(childsnap.val().IgramuserId);
var inprof = firebase.database().ref("InstaProfile");
inprof.orderByChild("Userid").equalTo(igid).once("value")
.then(function (inprofsnap) {
var data = inprofsnap.val()[Object.keys(inprofsnap.val())[0]];
instaprofile.push(data);
})
})
console.log(instaprofile);
});