你现在可能正在尝试做这样的事情:
var valueThatINeedToUseElsewhere;
dataLoad();
doSomethingWith(valueThatINeedToUseElsewhere);
不幸的是,这不起作用,因为(正如 Doug 所说)数据是从 Firebase 异步加载的。当您尝试使用 valueThatINeedToUseElsewhere 时,该值尚未加载。
为什么这不起作用,一三二测试
如果您像这样放置一些日志语句,最容易看到这一点:
console.log("Before starting to load value")
userReference.on('value',function(users){
console.log("Loaded value")
})
console.log("After starting to load value")
当你运行这段代码时,它会打印:
开始加载值之前
开始加载值后
加载值
这可能不是您期望的顺序。但它完美地解释了为什么你在尝试时不能使用 valueThatINeedToUseElsewhere:它还没有被加载。
重新定义问题
我发现处理这种情况的最佳方法是重新定义问题。您当前的代码是用“首先我们加载值,然后我们对值做一些事情”的逻辑编写的。对于异步加载,最好将其框定为“首先开始加载数据。一旦数据开始加载,就对其进行处理”。
在如下代码中:
function dataLoad() {
userReference.once('value',function(users){
var currentUser = firebase.auth().currentUser.uid
users.forEach(function(user){
if(user.key === currentUser) {
var valueThatINeedToUseElsewhere = user.val().userName
doSomethingWith(valueThatINeedToUseElsewhere)
}
})
})
}
如您所见,我们已将需要数据的代码移到数据可用时触发的回调中。这样您就可以保证在您致电doSomethingWith 时数据可用。我还更改了代码以使用 once,这(正如 Doug 所说)更适合您的用例。
还有两个步骤可以提高代码的灵活性和性能。
传入一个被调用的函数一旦数据被加载
首先:在最后一次更新中,对doSomethingWith 的调用是硬编码的,这意味着dataLoad() 和doSomethingWith 紧密联系在一起。将它们分开通常会更好。为此,我们可以将所谓的回调函数传入dataLoad,然后在加载数据时调用该函数。这非常类似于once() 所做的。让我们在实践中看看:
function dataLoad(callback) {
userReference.once('value',function(users){
var currentUser = firebase.auth().currentUser.uid
users.forEach(function(user){
if(user.key === currentUser) {
var valueThatINeedToUseElsewhere = user.val().userName
callback(valueThatINeedToUseElsewhere)
}
})
})
}
差别不大。但现在你可以像这样调用dataLoad:
dataLoad(doSomethingWith);
一旦加载数据,doSomethingWith 将被调用。
按key加载数据
最后的改变是优化。您当前的代码正在加载所有用户,而您只需要一个并且知道他们的密钥。仅加载特定用户会更有效,其中:
function dataLoad(callback) {
var currentUser = firebase.auth().currentUser.uid
userReference.child(currentUser).once('value',function(users){
var valueThatINeedToUseElsewhere = user.val().userName
callback(valueThatINeedToUseElsewhere)
})
}