然后,Javascript承诺在for循环中不按顺序执行Parse查询

Javascript then promise not sequential with Parse queries in for loop

本文关键字:顺序 执行 查询 Parse 循环 Javascript 承诺 for 然后      更新时间:2023-09-26

我编写了一系列函数,其中包括解析查询:

var query1 = new Parse.Query(Events);
    query1.equalTo("id_organizer", $localStorage.username);
    query1.greaterThanOrEqualTo("date_start",currentTime) 
    query1.each(function(results){
            var object = results;
            eventname = object.get("event_name");
            datestart = object.get("date_start");
            location = object.get("location");
            id_event = object.get("id_event")
            eventimagefile = object.get("event_image");
            eventimageurl = eventimagefile.url();
            description = object.get("description");
            id_organizer = object.get("id_organizer");
            min_twitter_followers = object.get("min_twitter_followers");
            min_instagram_followers = object.get("min_instagram_followers");
            min_facebook_friends = object.get("min_facebook_friends");
            max_number_requests = object.get("max_number_requests");
            eventDetails.push({'name':eventname,'location':location, 'datestart':datestart, 'eventphoto':eventimageurl,'organizer':id_organizer, 'description':description, 'minTwitterFollowers':min_twitter_followers, 'minFacebookFriends':min_facebook_friends, 'minInstagramFollowers':min_instagram_followers,'maxNumberRequests':max_number_requests, 'id_event':id_event})      
    }).then(function(){ 
        alert("start")
        var Attendees = Parse.Object.extend("Attendees");
        eventDetails.forEach(function(e){
            var query2 = new Parse.Query(Attendees);
            query2.equalTo("event_id", e.id_event);    
            query2.count({
                success: function(number) {
                    e["n_requests_received"] =  number;
                    alert("received")
                }
            })  
            var query3 = new Parse.Query(Attendees);
            query3.equalTo("event_id", e.id_event);
            query3.equalTo("status", "confirmed")
            query3.count({
                success: function(number) {
                    e["n_requests_confirmed"] =  number;
                   // alert("confirmed")
                }
            })
        })
}).then(function(){
    alert("end")
    alert(JSON.stringify(eventDetails))
    $scope.events = eventDetails;
    $localStorage.events = eventDetails;
    });
})

不幸的是,在"开始"之后立即打印警报"结束",而不等待foreach循环中的查询(query1、query2)执行。你知道我如何在下一个查询之前执行两个查询来进行for循环吗?

.then(function(){ 
        alert("start")
        var Attendees = Parse.Object.extend("Attendees");
        return Promise.all(eventDetails.map(detail => {
            return Promise.all([new Promise((res, rej) => {
                var query2 = new Parse.Query(Attendees);
                query2.equalTo("event_id", detail .id_event);    
                query2.count({
                    success: function(number) {
                        detail["n_requests_received"] =  number;
                        alert("received")
                        res('Some value if required'); //These are needed or promise chain will hang
                    }
                });
            }),
            new Promise((res, rej) => {
                var query3 = new Parse.Query(Attendees);
                query3.equalTo("event_id", detail .id_event);
                query3.equalTo("status", "confirmed")
                query3.count({
                    success: function(number) {
                        detail["n_requests_confirmed"] =  number;
                       // alert("confirmed")
                       res('Some value if required'); //These are needed or promise chain will hang
                    }
                });
            })]);
        }));
})

承诺链将等待承诺。也就是说,如果链中任何位置的.then接收到未解决的承诺,它将等待该承诺得到解决。

因此,您可以使用Promise.all,它需要一个promise数组,并在它们执行时解析。因此,映射到您的数组eventDetails上,从每个单元格创建promise。在每个单元格中,使用另一个Promise.all为两个Query对象创建两个新的promise。

这样,您的.then将等待eventDetails的承诺数组得到解决。然后eventDetails中的每个单元格都将等待您的查询数组解析。

注意:我们正在创建promise的new Promise()。它会通过两次回调来解决或拒绝承诺。这就是在promise中包装旧回调样式API的方法。然而,如果你不调用它们中的任何一个来解决或拒绝,那么整个承诺链可能会挂起(取决于其设计),等待该承诺解决。

希望这是有道理的。这是伪代码,但你应该明白。


免责声明我没有使用Parse.Query我不知道它是什么。然而,这个方法是我如何处理使用旧回调风格API的上述程序流的,在那里你基本上有嵌套的循环。


额外免责声明:我的例子是使用ES6语法。并不是所有的浏览器(IE)都支持这个功能。


编辑:操作要求一个不使用ES6箭头功能的版本,所以你来了。StackOverflow上有很多关于箭头函数、那个和谷歌的信息。正如你所看到的,在语法方面没有太大的区别。它的力量来自于它如何绑定作用域,以及当你以更实用的风格编写代码时。

.then(function(){ 
        alert("start")
        var Attendees = Parse.Object.extend("Attendees");
        return Promise.all(eventDetails.map(function (detail) {
            return Promise.all([new Promise(function (res, rej) {
                var query2 = new Parse.Query(Attendees);
                query2.equalTo("event_id", detail .id_event);    
                query2.count({
                    success: function(number) {
                        detail["n_requests_received"] =  number;
                        alert("received")
                        res('Some value if required'); //These are needed or promise chain will hang
                    }
                });
            }),
            new Promise(function (res, rej) {
                var query3 = new Parse.Query(Attendees);
                query3.equalTo("event_id", detail .id_event);
                query3.equalTo("status", "confirmed")
                query3.count({
                    success: function(number) {
                        detail["n_requests_confirmed"] =  number;
                       // alert("confirmed")
                       res('Some value if required'); //These are needed or promise chain will hang
                    }
                });
            })]);
        }));
})