链接然后没有按正确的顺序工作

时间:2017-04-09 08:26:07

标签: javascript firebase

我刚学会了链接'然后'在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(),set2(),set3(),set4()方法执行之前触发。这给了我不正确的结果。任何人都可以帮我解决这个问题吗?

EDIT1:请在此处查看checkAvg()方法:https://jsfiddle.net/jek9m7hn/。看起来有一些问题。

3 个答案:

答案 0 :(得分:1)

看起来set1正在调用异步的firebase 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 :(得分:1)

set1等以异步方式运行,但您不是在等待它们完成。您需要重写set1以返回完成所有异步工作的承诺,然后将代码更改为

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

但是,我建议重新编写所有这些代码。您不应该使用DOM作为存储值的主要位置。此外,您应该组合firebase调用,而不是为每个单独的值单独调用。

答案 2 :(得分:-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();
    });