尽管有希望,javascript promise会同步执行代码

时间:2018-01-28 11:34:23

标签: javascript jquery angularjs firebase firebase-realtime-database

所以基本上我有一个从firebase检索数据的Web应用程序。由于查询需要时间,我在javascript中使用了promises,以便我的代码在正确的时间执行。在函数getDataFirebase中,从firebase检索数据并将其推送到名为Collect的数组。因此,在推送1行之后,它再次向firebase查询要收集的另一个数据表,然后继续循环。所以,我在致电Firebase之前创建了一个承诺,然后再解决。但是,我没有在getDataUsers.once上做到这一点("值")。在那里,我正在触发事件而不是等待它返回 - for循环继续,并且所有回调都在稍后处理,但是解析是在for循环结束时,所以到那时为时已晚。

我在查询时使用了async关键字,希望它会导致for0loop等待该作业完成,但实际上它所做的全部操作都会导致回调返回一个承诺 - 由on函数加入。它已经调试了一段时间,并希望它能在适当的时间填充执行。有人请帮帮我吗? :(((

var promise = getDataFirebase();
promise.then(function () {
console.log(Collect);

console.log("firsst");
return getDataFirebaseUser();
 }).then(function () {

console.log("Second");

  });



function getDataFirebase() {
return new Promise(function (resolve, reject) {
    refReview.on("value", function (snap) {
        var data = snap.val();
        for (var key in data) {


            Collect.push({
                "RevieweeName": data[key].revieweeID.firstname.concat(" ", data[key].revieweeID.lastname),
                "ReviewerName": data[key].reviewerID.firstname.concat(" ", data[key].reviewerID.lastname),
                rating: data[key].rating,
                content: data[key].content,
                keyOfReviewee: data[key].revieweeID.userID
            })
            var getDataToUsers = firebase.database().ref("users").child(data[key].revieweeID.userID);
            getDataToUsers.once("value", async function (snap) {
                var fnLn = snap.val();
                var first = fnLn.isTerminated;
                console.log("terminateStatus", first);

            });


        }//end of for loop
        resolve();
    }); //end of snap 
});
}

根据代码输出控制台如下:

  Collect(array)
  first
  Second
  terminateStatus, 1

一定是

  Collect(array)
  first
  terminateStatus, 1
  second

1 个答案:

答案 0 :(得分:0)

首先,你误解了javascript中async / await的概念。请阅读mozilla的这个manual和一些例子来了解如何使用它。

回到你的问题,在你的例子中向回调函数添加“async”关键字不会改变任何东西。如果异步与否,Firebase将以相同的方式获取数据时调用该函数。在获取数据之前,在for循环结束时调用resolve,完成承诺。因此,在您获取数据之前,承诺已得到解决,这就是您最终获得terminateStatus的原因。

您可以使用从once方法返回的Promise,并等待它以便它不会退出for循环,直到获取所有数据。为此,您需要在第一次回调中添加async。见:

function getDataFirebase() {
   return new Promise(function (resolve, reject) {
refReview.on("value", async function (snap) {
    var data = snap.val();
    for (var key in data) {
        Collect.push({
            "RevieweeName": data[key].revieweeID.firstname.concat(" ", data[key].revieweeID.lastname),
            "ReviewerName": data[key].reviewerID.firstname.concat(" ", data[key].reviewerID.lastname),
            rating: data[key].rating,
            content: data[key].content,
            keyOfReviewee: data[key].revieweeID.userID
        })
        var getDataToUsers = firebase.database().ref("users").child(data[key].revieweeID.userID);
        var snapshot = await getDataToUsers.once("value");
        var fnLn = snapshot.val();
        var first = fnLn.isTerminated;
        console.log("terminateStatus", first);

    }//end of for loop
    resolve();
}); //end of snap 
});
}

但是,这仍然不是很好的代码,因为每次在不同的promise中调用refReview.on方法。您应该在应用程序中调用一次并附加回调,或者如果您打算为每个调用获取一个文档,则应使用refReview.once方法。