网络开发新手在这里 . 我使用Firebase作为我的后端,我有一种情况,我需要在DB中查询一个值,并使用该返回值在另一个查询中匹配到同一个DB .
这是我的代码:
function dataLoad() {
var valueThatINeedToUseElsewhere
userReference.on('value',function(users){
var currentUser = firebase.auth().currentUser.uid
users.forEach(function(user){
if(user.key === currentUser) {
valueThatINeedToUseElsewhere = user.val().userName
console.log(valueThatINeedToUseElsewhere)
}
})
})
console.log(valueThatINeedToUseElsewhere)
}
IF条件内的console.log记录正确的值 . 但是,上面的最后一个console.log没有记录任何内容,尽管变量名称在'on'函数之外声明 . 为什么会这样?我怎样才能真正使用'on'函数之外的数据?我需要使用它在另一个数据检索操作中执行类似的IF条件 .
谢谢!
2 回答
你现在可能会尝试这样做:
不幸的是,这并没有尝试使用
valueThatINeedToUseElsewhere
,该值尚未加载 .为什么这不起作用,一三二测试
如果您放置一些这样的日志语句,最容易看到这个:
当您运行此代码时,它会打印:
这可能不是您预期的顺序 . 但它完美地解释了为什么你尝试时不能使用
valueThatINeedToUseElsewhere
:它尚未加载 .重新定义问题
我发现处理这种情况的最好方法是重新构建问题 . 您当前的代码是用“首先加载值,然后我们用值做”的逻辑编写的 . 对于异步加载,最好将其框架为“首先开始加载数据 . 一旦数据开始加载,就用它做一些事情” .
在代码中看起来像:
当您将需要数据的代码移动到数据可用时触发的回调中时 . 这样,当您调用
doSomethingWith
时,可以保证数据可用 . 我也改变了代码使用once
,(正如Doug所说)对你的用例更好 .还需要采取两个步骤,以提高代码的灵活性和性能 .
传入加载数据后调用的函数
首先:在最后一次更新时,对
doSomethingWith
的调用是硬编码的,这意味着dataLoad()
和doSomethingWith
紧密相连 . 让它们更加分离通常会更好 . 为此,我们可以将所谓的回调函数传入dataLoad
,然后在加载数据时调用 . 这与once()
已经非常相似 . 让我们在实践中看到:没有太大的不同 . 但是现在你可以像这样调用
dataLoad
:一旦加载了数据,就会用数据调用
doSomethingWith
.按键加载数据
最后的改变是优化 . 您当前的代码正在加载所有用户,而您只需要一个并知道他们的密钥 . 仅加载特定用户的效率更高,具有:
on()是异步的并立即返回,这意味着您的控制台日志将显示未定义的值 . 您传递给on()的回调仅在结果可用时才会运行,并且无法保证会多快发生 . 您应该只在完成后使用异步调用中的值 - 在完成异步调用之前不要尝试使代码阻塞 .
如果您只需要一次一个位置的值,也可以考虑使用once()而不是on() . 您可以使用其返回的promise在加载所需数据后链接一些额外的工作 . 它也是异步的(就像返回promise的所有其他方法一样) .
要详细了解Firebase API为什么是异步的,以及这对您的应用意味着什么,read this blog .