Firebase value is undefined when it is not supposed to be

狂风中的少年 提交于 2020-01-06 06:06:45

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!