我过去几个小时一直在研究局部变量和全局变量。我从这个问题“How do I change the value of a global variable inside of a function”和其他一些问题中发现,如果变量是在函数之前声明的(在它之外),那么当你想要更新函数中的变量时,你只需要说“变量=空白”而不是“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
,从Promise
函数返回initApp
,或者更改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 / etc中处理。