函数内部的Firebase查询返回null [英] Firebase Query inside function returns null

查看:80
本文介绍了函数内部的Firebase查询返回null的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用具有Firebase的javascript创建学生出勤跟踪应用程序.

但是我有一个问题,我试图在一个函数中查询并使该函数返回这些数据.

但是当我尝试时,它什么也没返回. 未定义"

这是我的代码

var root = 'https://path.firebaseio.com';
function initFireSubjects(){
   var db = {};
   db.connection = new Firebase(root + '/subjects');
   db.addSubject = function (year, code, name) {
       this.connection.child(year).push({
           code: code,
           name: name
       });
    };
    db.getAll = function (year) {
        var value;
        this.connection.child(year).on('value', function (snapshot) {
            value = snapshot.val();
        });
        return value;
    };
}

这是我要测试的代码

var db = initFireSubjects();
var test = db.getAll('2014');
console.log(test);

数据结构如下

subject:{
    '2014':{
        randomKey1:{
            code:'eng1',
            name:'English 1'
        },
        randomKey2:{
            code:'math1',
            name:'Mathematics 1'
        },
        randomKey3:{
            code:'sci1',
            name:'Science 1'
        }
    },
    '2015':{
        randomKey4:{
            code:'polsci1',
            name:'Political Science 1'
        },
        randomKey5:{
            code:'comprog',
            name:'Computer Programming'
        }
    }
}

这种情况是,我可以这样提取数据

db.getAll = function(year){
    var value;
    this.connection.child(year).on('value',function(snapshot){
        value = snapshot.val();
        console.log(value);
    }
}

我不知道为什么它不能以面向对象的方式提取数据.

有输入吗?

谢谢.

解决方案

您所看到的与OO无关,但实际上与Firebase(像大多数现代网络一样)实际上是异步的. /p>

当您使用on向Firebase注册事件处理程序时,Firebase 会启动来检索并监控该位置的数据.由于检索数据可能需要一些时间(并且更新的数据可能会随时到达),因此浏览器会继续执行JavaScript.数据可用后,将调用您的回调函数.

如果我们编写的代码稍有不同,则更容易看到正在发生的事情:

/* 1 */ db.getAll = function (year) {
/* 2 */     var value;
/* 3 */     this.connection.child(year).on('value', db.onValue);
/* 4 */     return value;
/* 5 */ };
/* 6 */ db.onValue = function(snapshot) {
/* 7 */     value = snapshot.val();
/* 8 */     console.log(value);
/* 9 */ });

当您的getAll函数执行时,它首先声明一个value变量.在3行中,它告诉Firebase从服务器获取年份的值时调用db.onValue. Firebase退出以获取该值,但是您的JavaScript继续执行.因此,在第4行中,您然后返回value,它仍未初始化.所以您要返回undefined.

有时,您要求的值从Firebase的服务器返回.发生这种情况时,将调用onValue函数,并在第8行中打印出年份.

一件事可能会帮助您接受为何有用:如果另一件事现在更新Firebase中的年份,则会再次调用 onValue函数. Firebase不仅会检索数据一次,还会监视数据更改的位置.

异步加载不是Firebase独有的.几乎每个开始使用JavaScript进行现代Web编程的人都在某个时候被这一点所困扰.您能做的最好的事情就是迅速接受并接受异步性(甚至是一个词?)并加以处理.

进行处理,通常意味着您将要使用新值执行的操作移至回调函数内部.因此,我在第8行中添加的console.log也可能会使用document.querySelector('#currentyear').textContent = value之类的内容来更新您的UI.

也请阅读此答案(它使用的是AngularFire,但问题是相同的): 解决方案

What you're seeing has little to do with OO, but everything with the fact that Firebase is (like most of the modern web) asynchronous in nature.

When you register an event handler with Firebase using on, Firebase starts to retrieve and monitor the data at that location. Since it may take some time to retrieve the data (and updated data may arrive at any time) the browser continues executing your JavaScript. Once the data is available, your callback function is invoked.

It is a bit easier to see what's happening if we write your code slightly differently:

/* 1 */ db.getAll = function (year) {
/* 2 */     var value;
/* 3 */     this.connection.child(year).on('value', db.onValue);
/* 4 */     return value;
/* 5 */ };
/* 6 */ db.onValue = function(snapshot) {
/* 7 */     value = snapshot.val();
/* 8 */     console.log(value);
/* 9 */ });

When your getAll function executes, it declares a value variable first. In line 3 it then tells Firebase to call db.onValue when it gets a value for the year from the server. Firebase goes off to retrieve that value, but your JavaScript continues to execute. So in line 4 you then return value, which is still uninitialized. So you're returning undefined.

At some point the value you've asked for comes back from Firebase's servers. When that happens, the onValue function is invoked and it prints out the year in line 8.

One thing that may help you accept why this is useful: if another now updates the year in your Firebase, the onValue function will be invoked again. Firebase doesn't just retrieve the data once, it monitors the location for changes in the data.

The asynchronous loading is not unique to Firebase. Pretty much everyone that gets started programming for the modern web in JavaScript gets bitten by this at some point. The best thing you can do is accept and embrace the asynchronicity (is that even a word?) quickly and deal with it.

Dealing with it, usually means that you move the operation that you want to execute with the new values to inside the callback function. So the console.log that I added in line 8, could also be updating your UI with something like document.querySelector('#currentyear').textContent = value.

Also read this answer (it is using AngularFire, but the problem is the same): Asynchronous access to an array in Firebase and some of the other questions linked from there.

这篇关于函数内部的Firebase查询返回null的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆