Javascript:将数据从 Firebase DB 加载到生成的输入字段中
这是我的数据结构:
使用
Total
(即
R
又称路线的数量)我使用此处的代码生成 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;
})
我不明白哪里出了问题。
我将我的回复分为两个部分:问题和解决方案。
问题 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);
})
}
仅当
firebase
的异步调用得到解析时,
f1
函数才会运行(
then
会执行此操作)。因此,假设此请求进入某个队列,但这不会阻止其他函数执行,因为工作已经完成,并且请求已由
f2
放置。如果您查看图像并将其与代码关联起来,您将看到,当
y
的值增加并达到
3
时,我们开始从
firebase
获取响应。然后执行
document.getElement
,但只有
y
的最终值需要考虑,其他所有值都已过去。在其他情况下,可能会发生这种情况,在 for 循环结束时可能会得到/不会得到解决。这会导致不一致。
对于一个值,这很简单,因为只有一个值需要解析,一个相应的字段需要填充。所以没有不一致。简而言之,它是不可预测的。
问题 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;
}
}
希望这会起作用!试试看。
我非常确定问题出在您的 for 循环上。问题可能是在承诺返回时 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;
}));