尽管有外部声明,但仍无法全局查看Firebase数据库中的变量. (javascript) [英] Variable from firebase database isn't seen globally despite outer declaration. (javascript)
问题描述
过去的几个小时中,我一直在研究局部和全局变量.我从这个问题中发现的内容"
I have been doing research for the past few hours on local and global variables. What I found from this question "How do I change the value of a global variable inside of a function", and a few others was that if the variable was stated before the function (outside of it) then when you want to update the variable in a function you just say the "variable = blank" without "var" proceeding it.
如果您查看下面的功能,我有三个警报,所有警报都通过firebase来警告当前登录用户的用户名. firebase引用中的第一个警报显示用户名没问题.其他两个警报未定义".我需要能够在所有三个位置引用该变量,我做错了什么吗?还是有另一种方法可以有效并且可能更有效?
If you look at the function below I have three alerts, all alerting the username of the currently logged in user via firebase. The first alert, inside the firebase reference, displays the username no problem. The other two alert "undefined". I need to be able to reference the variable in all three locations, is there something I did wrong? or is there another way to do this that works and is maybe more efficient?
var database = firebase.database();
var username;
function initApp() {
// Listen for auth state changes.
// [START authstatelistener]
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
// User is signed in.
var displayName = user.displayName;
var email = user.email;
var emailVerified = user.emailVerified;
var photoURL = user.photoURL;
var isAnonymous = user.isAnonymous;
var uid = user.uid;
var providerData = user.providerData;
var ref = firebase.database().ref("users/" + uid);
ref.once("value").then(function(snapshot) {
username = snapshot.child("username").val();
alert(username);
});
alert(username);
}
});
}
alert(username);
window.onload = function() {
initApp();
};
我了解这似乎与其他问题相似,但是尽管有许多不同的方法,但这些答案似乎并没有奏效.预先感谢您的所有帮助,我希望这只是一个愚蠢的错误.
I understand this may seem similar to other questions, but those answers didn't seem to work despite numerous different approaches. Thanks in advance for all of your help, I am hoping this is just a stupid mistake.
推荐答案
我认为您对代码的异步性质感到困惑.您的用户名只能在此处的回调中使用:
I think you are confused about the asynchronous nature of your code. Your username is only going to be available in the callback here:
ref.once("value").then(function(snapshot) {
username = snapshot.child("username").val();
alert(username);
});
因为ref.once("value")
是异步的(紧接在上面的代码块之后的alert
将始终在您的.then
回调执行之前被调用).任何依赖username
的代码都必须确保在执行之前异步调用已完成.
because ref.once("value")
is asynchronous (the alert
immediately following the code block above will always be called before your .then
callback executes). Any code that depends on username
is going to have to ensure that the asynchronous call is complete before executing.
有多种方法可以完成此操作,例如:async/await
,从initApp
函数返回Promise
或更改initApp
以接受在异步操作后运行依赖代码的回调做完了.这是一个返回Promise
的示例:
There are a number of ways to accomplish this, such as: async/await
, returning a Promise
from your initApp
function, or changing initApp
to accept a callback that runs your dependent code once the async stuff is complete. Here is an example that returns a Promise
:
function initApp() {
return new Promise(function(resolve, reject) {
// Listen for auth state changes.
// [START authstatelistener]
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
// User is signed in.
var displayName = user.displayName;
var email = user.email;
var emailVerified = user.emailVerified;
var photoURL = user.photoURL;
var isAnonymous = user.isAnonymous;
var uid = user.uid;
var providerData = user.providerData;
var ref = firebase.database().ref("users/" + uid);
ref.once("value").then(function(snapshot) {
username = snapshot.child("username").val();
resolve(username);
});
} else {
// no username, reject
reject("User is not logged in")
}
});
});
}
window.onload = function() {
initApp().then(function(username) {
alert(username);
// do things that depend on user/username
}).catch(function(error) {
alert(error);
});
};
Once the Promise
is in place, you can use async/await to make your code feel more synchronous:
window.onload = async function() {
try {
const username = await initApp();
alert(username);
} catch(e) {
alert(e);
}
};
请记住,您仍然无法在此功能之外alert
用户名-依赖异步数据的任何代码必须等待数据准备就绪即在其中处理then
/callback/etc.
Keep in mind that you will still not be able to alert
the username outside of this function - any code that relies on the async data must wait until that data is ready i.e. be handled in a then
/callback/etc.
这篇关于尽管有外部声明,但仍无法全局查看Firebase数据库中的变量. (javascript)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!