2017-04-09 37 views
1

我刚刚了解JavaScript中的链接'然后',但我面临一个问题,即最后一个块然后执行前一个然后块已完成。 相关的代码是:被链接,然后不正确的顺序

firebaseRef.once("value") 
    .then(function(snapshot) { 
     snapshot.forEach(function(childSnapshot) { 
      //getting key of the child 
      var pid=childSnapshot.key; 
      // childData will be the actual contents of the child 
      var childData = childSnapshot.val(); 
      var name=childData.name; 
      pids.push(pid); 
      names.push(name); 
    }); 
}) 
    .then(function() { 
     for (var i = 0; i < pids.length; i++) { 
      $("#pid"+(i+1)).text(pids[i]); 
      $("#name"+(i+1)).text(names[i]); 
     } 
     set1(); 
     set2(); 
     set3(); 
     set4(); 
    }) 
    .then(function(){ 
     calcAvg(); 
    }); 

这里,calcAvg()的SET1(),设定2(),SET3(),SET4()方法已经执行之前触发关闭。这给了我不正确的结果。任何人都可以帮我解决这个问题吗?

编辑1:请检查checkAvg()方法在这里:https://jsfiddle.net/jek9m7hn/。看起来像是由于它的一些问题。

+1

'set1-4()'和'calcAvg()'做了什么?你可以发布此代码供我们检查吗? – gyre

+0

请检查https://jsfiddle.net/jek9m7hn/。我已经添加了set1()和calcAvg()的代码。 set2(),set3(),set4()与set1()类似。如果您发现任何问题,请告诉我。 –

+0

@torazaburo我试着在calcAvg中放入一个alert语句,并看到在setn函数之前执行的警报。另外,我在setn()中设置了值,然后在calcAvg()中计算它们的平均值。由于calcAvg在setn执行之前执行,所以我得到的平均值为NaN。 –

回答

-1

在函数中声明的变量不能在链接函数内部访问。 JS中的一个变量有一个块范围,在一个块范围内声明的变量不能在另一个块范围内访问。为了解决你的问题,你可以尝试先外宣布PID然后,即重构代码如下

var pids = [], names = []; 
firebaseRef.once("value") 
    .then(function(snapshot) { 
     snapshot.forEach(function(childSnapshot) { 
      //getting key of the child 
      var pid=childSnapshot.key; 
      // childData will be the actual contents of the child 
      var childData = childSnapshot.val(); 
      var name=childData.name; 
      pids.push(pid); 
      names.push(name); 
    }); 
}) 
    .then(function() { 
     for (var i = 0; i < pids.length; i++) { 
      $("#pid"+(i+1)).text(pids[i]); 
      $("#name"+(i+1)).text(names[i]); 
     } 
     set1(); 
     set2(); 
     set3(); 
     set4(); 
    }) 
    .then(function(){ 
     calcAvg(); 
    }); 
+0

这是如何解释OP声称要观察或修复的行为?你的代码可能会导致引用错误,因为'pid'现在没有声明。 – 2017-04-09 09:01:14

1

貌似set1呼唤火力API是异步。 你应该用你的一套方法,以确保Promise.all所有的承诺都解决了,这样的事情:

function set1() { 
    ... // calculate stuff 
    var p1 = guideRef.child("presentation").once('value'); 
    p1.then(...). 
    ... // more calculations 

    return Promise.all([p1, p2, ...]) // all your async calls 
} 

然后,在你的主要功能你可以这样做:

for (var i = 0; i < pids.length; i++) { 
    $("#pid"+(i+1)).text(pids[i]); 
    $("#name"+(i+1)).text(names[i]); 
} 

return Promise.all([set1(), set2(), set3(), set4()]) 

我认为重构代码可以减少这种复杂性,但这不在问题的范围之内。

1

set1等异步操作,但您不等待它们完成。你需要重写set1返回承诺为当所有的异步工作完成后,你的代码更改为类似

.then(set1).then(set2).then(set3).then(set4).then(calcAvg) 

不过,我会建议重新编写这些代码。你不应该真的使用DOM作为存储值的主要地方。此外,您应该结合Firebase调用,而不是为每个单独的值分别调用。