javascript承诺仍然同步执行代码

时间:2018-01-27 20:21:09

标签: javascript firebase firebase-realtime-database

所以基本上我有一个从firebase检索数据的Web应用程序。并且由于从firebase检索数据需要花费大量时间,因此我使用promise来使我的代码在正确的时间填充。这是我的代码:

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 
    });
}

所以在函数getDataFirebase中,从firebase检索数据并将其推送到名为Collect的数组。因此,在按下1行之后,它再次向firebase查询另一个数据表,然后继续循环。这里的问题是,我想在结算承诺之前完成所有流程。

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

 Collect (array)
first
Second
terminateStatus, 1

一定是

   Collect (array)
 first
terminateStatus,1
second

1 个答案:

答案 0 :(得分:0)

我不是100%确定您的代码是如何工作的,但看起来您在refReview.on("value")做了正确的事情:在调用Firebase之前创建一个承诺,然后再解析它。但是你没有在getDataToUsers.once("value")上这样做。在那里,你正在触发事件而不是等待它返回 - for循环继续,所有的回调都在稍后处理,但是resolve在for循环的末尾,所以它也是那么晚了。

我的猜测是你认为async关键字会导致for循环等待该作业完成,但实际上它所做的只是导致回调返回一个promise - 这被on功能。

你有几个选择,但最好的方法是使用Promise.all,它接受​​一系列的承诺并等待它们全部解决 - 但你应该使用Firebase's Promise API而不是将承诺捆绑到事件API上。所以它看起来像:

refReview.once('value')
    .then(snap => Promise.all(snap.val().map(item =>
        firebase.database()
            .ref("users")
            .child(item.revieweeID.userID)
            .once('value')
            .then(snap => {
                console.log('terminated');
            ])
    })));

(添加了实际功能,natch除外)