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

时间:2022-05-01 21:01:31

so basically i have a web application that retrieves data from firebase. Since it takes time to query, i used promises in javascript so that my code will execute at the right time. In function getDataFirebase, data is retrieved from firebase and is push to an array called Collect. So, after pushing 1 row, it query again to the firebase for another table of data to be collected then continues the loop. So, i create a promise before calling Firebase, and then resolving afterwards. But, im not doing that on getDataUsers.once("value"). There, i'm firing event and not waiting for it to return - the for-loop continues on, and all the callbacks processed later, but resolve is at the end of the for-loop, so its too late by then.

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

I used the async keyword in the when querying hoping that it would cause the for0loop to wait for that job to complete, but actually all it does here is causing the callback to return a promise - which is ingored by the on function. Its been a while already debugging and hoping that it would populate the execution at the right time. Someone pleasee help me? :(((

我在查询时使用了async关键字,希望它会导致for0loop等待该作业完成,但实际上它所做的一切都是导致回调返回一个promise - 由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 
});
}

Output of console according to the code is as follows:

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

  Collect(array)
  first
  Second
  terminateStatus, 1

it must be

一定是

  Collect(array)
  first
  terminateStatus, 1
  second

1 个解决方案

#1


0  

First of all, you misunderstood the concepts of async/await in javascript. Please, read this manual from mozilla and some examples to understand how to use it.

首先,你误解了javascript中async / await的概念。请从mozilla和一些示例中阅读本手册以了解如何使用它。

Coming back to your problem, adding "async" keyword to the callback function in your example does not change anything. Firebase will call that function when it fetches data the same way if its async or not. And before it fetches data, you call resolve at the end of for loop, completing promise. So the promise is resolved before you fetch the data, which is why you get terminateStatus at the end.

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

You could use Promise returned from once method, and await it so that it wont go out of for loop, until all the data fetched. To do that, you have add async to first callback. See this:

您可以使用从一次方法返回的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 
});
}

However, this is still not very good piece of code since you call refReview.on method each time inside a different promise. You should either call it once in your app and attach a callback, or you should use refReview.once method if you just intend to fetch one document for each call.

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

#1


0  

First of all, you misunderstood the concepts of async/await in javascript. Please, read this manual from mozilla and some examples to understand how to use it.

首先,你误解了javascript中async / await的概念。请从mozilla和一些示例中阅读本手册以了解如何使用它。

Coming back to your problem, adding "async" keyword to the callback function in your example does not change anything. Firebase will call that function when it fetches data the same way if its async or not. And before it fetches data, you call resolve at the end of for loop, completing promise. So the promise is resolved before you fetch the data, which is why you get terminateStatus at the end.

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

You could use Promise returned from once method, and await it so that it wont go out of for loop, until all the data fetched. To do that, you have add async to first callback. See this:

您可以使用从一次方法返回的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 
});
}

However, this is still not very good piece of code since you call refReview.on method each time inside a different promise. You should either call it once in your app and attach a callback, or you should use refReview.once method if you just intend to fetch one document for each call.

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