问题
I am working on a firebase project. During testing the
return user.val().name;
will return an
undefined
value however the
console.log(user.val().name)
will return the actual string stored in the .name field. Why is that. Also even if assign the
user.val().name
to a variable, the variable remains undefined.Please help figure out why this happens. I am printing it to a csv.
Here is my code:
var database = firebase.database();
var ref2 = database.ref('information/');
var id;
var name;
ref2.on("value", function (one) {
one.forEach(function (two) {
if (typeof two.val().Id !== 'undefined') {
id = two.val().Id;
name = program(id); //name undefined
}
else {
id = "";
}
csv = name + "," + id +"\n";
});
download(csv);
});
};
function program (id) {
var database = firebase.database();
var ref = database.ref("users/" + id + "/");
ref.on('value',function(user){
if (typeof user.val().name === 'undefined') {
return null;
}
else {
console.log(user.val().name); //this doesnt show undefined
return user.val().name; //this shows undefined when appended to a html element
}
})
}
Note: In the firebase database, the name value is not null. It has a string added to it.
回答1:
I second with Frank's reason on why your function program()
doesn't work. Because ref.on('value'...
makes an asynchronous call, program()
does not wait for the completion of ref.on
and exists with an undefined
return value.
What you could instead do is use Promises. Wrap the statements inside your program()
function within a Promise, and upon completion of the asynchronous call, resolve
or reject
based on the result it gives.
Here's your function with Promises:
function program(id) {
return new Promise(function (resolve, reject) {
try {
var database = firebase.database();
var ref = database.ref("users/" + id + "/");
ref.on('value', function (user) {
if (typeof user.val().name === 'undefined') {
resolve(null);
} else {
console.log(user.val().name);
resolve(user.val().name);
}
})
} catch (e) {
reject(e)
}
});
}
And then, here's how you can read the result:
program(id).then(function (result) {
console.log(result)
//Do what you want with the result here
}).catch(function (error) {
console.log(error)
})
Note: You're executing this block in a for-each statement. If you're using Promises, you'd also need to look into how to use Promises inside a loop. For reference, check Promise.all()
回答2:
Most likely you are trying to use the returned name in the code that calls your program
function. E.g.
var name = program("1234");
console.log(name); // this will print undefined
This will not work, since your program()
is not actually returning name. Data is loaded from Firebase asynchronously. By the time program()
exits, the data isn't loaded yet.
This is easiest to see by putting a few log statements into the code:
function program (id) {
var database = firebase.database();
var ref = database.ref("users/" + id + "/");
console.log("Before attaching listener");
ref.on('value',function(user){
console.log("Got value from database");
})
console.log("After attaching listener, exiting function");
}
This will print:
Before attaching listener
After attaching listener, exiting function
Got value from database
This is likely not the order that you expected, but it is working as designed. Instead of waiting for the data to be loaded (and making the browser/user wait), your code continues. Then when the data is loaded, your callback is invoked. But in your original code that means that your return
statement is unable to return the name to the original caller.
This is precisely the reason why the Firebase Database (and most web APIs) use callbacks like the one you pass into on()
. This callback is invoked when the data is available and is the only place where you can access the user data. So any code that requires the data you just loaded must be inside that callback, or be called from inside that callback. E.g.
function program (id) {
var database = firebase.database();
var ref = database.ref("users/" + id + "/");
ref.on('value',function(user){
if (typeof user.val().name === 'undefined') {
return null;
}
else {
console.log(user.val().name);
appendToHtmlElement(user.val().name);
}
})
}
回答3:
Firebase> DataBase> Role
Have you changed the value of rules?
Comment Example!
That can get the value after moving to name.
var ref = database.ref ("users/" + id + "/name");
ref.on ('value', function (user) {
if (user.val ()! = null) {
console.log (user.val ())
}
}
If not, let's worry about it.
回答4:
You should receive the returned value.
var name = ref.on('value',function(user){
if (typeof user.val().name === 'undefined') {
return null;
}
else {
console.log(user.val().name); //this doesnt show undefined
return user.val().name; //this shows undefined when appended to a html element
}
})
then use return name
to get the value. or simply return the return ref.on('value' ...
来源:https://stackoverflow.com/questions/47566533/firebase-value-is-undefined-when-it-is-not-supposed-to-be