在过去的几个小时里,我一直在研究局部和全局变量。我从这个问题"如何更改函数内部全局变量的值"以及其他一些问题是,如果变量是在函数之前(在函数外部)声明的,那么当您想更新函数中的变量时,您只需说"变量 = 空白"而没有"var"继续它。
如果您查看下面的功能,我有三个警报,所有警报都通过Firebase提醒当前登录用户的用户名。Firebase 参考中的第一个提醒会显示用户名没有问题。另外两个警报"未定义"。我需要能够在所有三个位置引用变量,我做错了什么吗?或者有没有另一种有效且可能更有效的方法?
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();
};
我知道这似乎与其他问题相似,但尽管有许多不同的方法,这些答案似乎不起作用。提前感谢您的所有帮助,我希望这只是一个愚蠢的错误。
我认为您对代码的异步性质感到困惑。您的用户名只会在此处的回调中可用:
ref.once("value").then(function(snapshot) {
username = snapshot.child("username").val();
alert(username);
});
因为ref.once("value")
是异步的(紧跟在上述代码块之后的alert
将始终在执行.then
回调之前调用)。任何依赖于username
的代码都必须确保异步调用在执行之前完成。
有许多方法可以实现此目的,例如:async/await
,从initApp
函数返回Promise
,或更改initApp
以接受在异步内容完成后运行依赖代码的回调。下面是一个返回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);
});
};
一旦Promise
到位,就可以使用 async/await 来使代码感觉更加同步:
window.onload = async function() {
try {
const username = await initApp();
alert(username);
} catch(e) {
alert(e);
}
};
请记住,您仍然无法在此函数之外alert
用户名 - 任何依赖于异步数据的代码都必须等到该数据准备就绪,即在then
/callback/等中处理。