Javascript:将Firebase数据库中的数据加载到生成的输入字段

时间:2018-02-19 22:06:59

标签: javascript firebase firebase-realtime-database

这是我的数据结构:

enter image description here

使用Total(计数为R aka路由)我使用此处的代码生成3个输入框:

var rootRef = firebase.database().ref().child('Lane').child('Total')

function calcVelocity(snapshot) {
   var td;

   td = snapshot.val();

   return td;
}

function getVelocity() {
   return rootRef.once('value').then(calcVelocity);
}

getVelocity().then(function(vel) {
    for(i =0; i < vel; i ++){
        document.getElementById("insert_lanes").innerHTML +=  '<input type="text" class="form-control" id="R'+i+'" name="Schoolname[]" value="" placeholder="Freq Rank"><br>'
    }

工作正常,有3个输入框使用ID R1 R2 R3生成。

现在加载数据:

function f1(snapshot){
    var hol;
    hol = snapshot.val();
    return hol
}

function f2(i){
    return firebase.database().ref('Lane/R'+i+"/Dest").once('value').then(f1)
}

for(y =0; y<3; y++){
f2(y).then(function(veg){
    document.getElementById("R"+y).value = veg;
})
}

会引发错误Uncaught (in promise) TypeError: Cannot set property 'value' of null

然而,当我只对其中一个人这样做时,它可以工作:

function f1(snapshot){
    var hol;
    hol = snapshot.val();
    return hol
}

function f2(i){
    return firebase.database().ref('Lane/R'+i+"/Dest").once('value').then(f1)
}

y=1
f2(y).then(function(veg){
    document.getElementById("R"+y).value = veg;
})

我不明白什么是错的。

2 个答案:

答案 0 :(得分:1)

我很确定问题出在你的for循环中。当promises返回时,问题可能是for循环中的y变量的范围问题。尝试展开for循环,看看是否有效:

f2(0).then(function(veg){
    document.getElementById("R"+ 0).value = veg;
}));

f2(1).then(function(veg){
    document.getElementById("R"+ 1).value = veg;
}));

f2(2).then(function(veg){
    document.getElementById("R" + 2).value = veg;
}));

答案 1 :(得分:1)

我将分两部分打破我的回答:问题和解决方案。

问题1

问题在于firebase函数的异步调用。让我们做一些挖掘,这将使事情变得清晰。我添加了一些console输出以查看其中的位置。请注意,我还在这些函数之外声明y以跟踪循环迭代。

var y = 0;

function f1(snapshot) {
    console.log("in f1", y);
    var hol;
    hol = snapshot.val();
    console.log("in f1 hol", hol, y);
    return hol;
}

function f2(i) {
    console.log("in f2", y);
    return firebase.database().ref('Lane/R' + i + "/Dest").once('value').then(f1);
}

for (; y < 3; y++) {
    console.log("in for", y);
    f2(y).then(function(veg) {
        console.log("resolved", y);
        document.getElementById("R" + y).value = veg;
        console.log(y);
    })
}

当你运行它时,输出将是这样的:enter image description here

f1函数仅在firebase的异步调用解析后运行(then执行此操作)。因此,这个请求可以在某个队列中进行,但这并不会阻止其他函数执行,因为工作已经完成并且请求已由f2发出。如果您看到图片并将其与代码相关联,您会看到我们开始从firebase获得响应,y的时间值已递增并达到3。然后执行document.getElement,但只考虑y的最终值,所有其他值现在都已过去。在其他情况下,可能会发生这种情况可能会在循环结束时得到/未得到解决。这会导致不一致。

对于一个值,它是直接的,因为只有一个值需要解析,一个相应的字段要填充。所以没有不一致之处。简而言之,这是不可预测的。

问题2

让我们回顾一下另一个并发问题。显然,当您访问输入字段以填充它们时,它们甚至都不存在!它们尚未添加到DOM中。这又是解决回调或承诺的复杂情况。 这可能是Uncaught (in promise) TypeError: Cannot set property 'value' of null即将到来的原因。

解决方案

看一下下面这段代码。我试图尽可能少地改变并使其发挥作用。

<强> getVelocity

getVelocity().then(function(vel) {
    //pass the value of Total in vel

    for (var i = 0; i < vel; i++) { //vel = 5
        document.getElementById("insert_lanes").innerHTML += '<input type="text" class="form-control" id="R' + i + '"><br>';
    }
    // the input fields are created R0, R1, ...... 
    loadSnapshot(); //calling the next function
});

之后

var laneRef = firebase.database().ref('/Lane');

var getSnap = function(){
    return laneRef.once('value');
}

function loadSnapshot(){
    getSnap().then(fillInputFields);
}

function fillInputFields(snapshot){
    for(var i=0; i<5; i++) {
        var v = snapshot.child('R'+i).child('Dest').val();
        // console.log(v);
        // console.log((document).getElementById('R'+i));
        document.getElementById('R'+i).value = v;
    }
}

我希望这会奏效!试一试。