【问题标题】:javascript promise executes code synchronously despite of promise尽管有承诺,javascript promise 仍会同步执行代码
【发布时间】:2018-07-07 05:46:00
【问题描述】:

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

我在查询时使用了 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 
});
}

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

  Collect(array)
  first
  Second
  terminateStatus, 1

一定是

  Collect(array)
  first
  terminateStatus, 1
  second

【问题讨论】:

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


    【解决方案1】:

    首先,您误解了 javascript 中的 async/await 的概念。请阅读来自 mozilla 的 manual 和一些示例以了解如何使用它。

    回到您的问题,在您的示例中向回调函数添加“async”关键字不会改变任何内容。 Firebase 将在以相同方式获取数据时调用该函数,无论其是否异步。在它获取数据之前,您在 for 循环结束时调用 resolve,完成承诺。因此,promise 在您获取数据之前就已解决,这就是您在最后得到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 方法。

    【讨论】:

    • 它有效。非常感谢阿贝亚兹。我会听取您的建议并改进代码。
    猜你喜欢
    • 2016-02-01
    • 1970-01-01
    • 2020-11-25
    • 2020-08-10
    • 2021-12-22
    • 1970-01-01
    • 2021-01-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多