首页 文章

使用从Firebase获取的数据获取Javascript

提问于
浏览
0

网络开发新手在这里 . 我使用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 回答

  • 1

    你现在可能会尝试这样做:

    var valueThatINeedToUseElsewhere;
    dataLoad();
    doSomethingWith(valueThatINeedToUseElsewhere);
    

    不幸的是,这并没有尝试使用 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 .

    按键加载数据

    最后的改变是优化 . 您当前的代码正在加载所有用户,而您只需要一个并知道他们的密钥 . 仅加载特定用户的效率更高,具有:

    function dataLoad(callback) {
        var currentUser = firebase.auth().currentUser.uid
        userReference.child(currentUser).once('value',function(users){
            var valueThatINeedToUseElsewhere = user.val().userName
            callback(valueThatINeedToUseElsewhere)
        })
    }
    
  • 0

    on()是异步的并立即返回,这意味着您的控制台日志将显示未定义的值 . 您传递给on()的回调仅在结果可用时才会运行,并且无法保证会多快发生 . 您应该只在完成后使用异步调用中的值 - 在完成异步调用之前不要尝试使代码阻塞 .

    如果您只需要一次一个位置的值,也可以考虑使用once()而不是on() . 您可以使用其返回的promise在加载所需数据后链接一些额外的工作 . 它也是异步的(就像返回promise的所有其他方法一样) .

    要详细了解Firebase API为什么是异步的,以及这对您的应用意味着什么,read this blog .

相关问题