如何使用Promise为对象数组中的每个元素进行Ajax调用?

3

I have this code:

       // _arrOfUsers = array of objects, each object represents a user. 
       //For example, a single object may be something like {name:"mike", id:"123"}    

            var _successUsers = function (_arrOfUsers) {            
                    var promises = [];   //empty array of promises

                        _arrOfUsers.forEach(function (user) {
                            promises.push(function () {
                                return $.Deferred(function (dfd) {
                                     $.post("//sessionID",
                                                queryServ.getAllUserDomainCommentsFunc("//currentDomainID", user.iD, "//currentDomainID", "//currentURL"),
                                        'text', 'text/plain', this,
                                        function (dataX) {
                                            dfd.resolve(dataX);
                                        });
                                }).promise();
                            });
                    });

                    $.when(promises).then(function (results) {
                        console.log(results);
                    });

                };

理解这段代码的一些要素:

**** Ajax调用设置

  • url: sessionURL
  • data: 发送到服务器的数据是一个对模块queryServ.js的外部调用,调用函数为getAllUserDomainCommentsFunct,它返回一个JSON对象。 它需要这些参数才能工作:currentDomain,userID,currentDomain(再次),currentURL
  • type: text
  • contentType: text/plain
  • context: this

**** 评论是一个类似于jsonObject的对象 {id: "998", textOfcomment:"I commented this", target: "//targetID"}.

我想做的是为数组“_arrOfUsers”中的每个用户都进行一次ajax调用,从服务器提取他的所有评论;在完成所有“提取”操作之后,我需要获取所有结果(即来自所有用户的所有评论)并在控制台中打印出来。 对于我的代码,顺序非常重要,这就是为什么我在使用Promises的原因。

我在StackOverflow上的JSfiddle中找到了此算法的结构,但是它对我没有用,因为它返回一个函数数组,我无法理解为什么,可能是因为我在职业生涯中从未使用过Promise。

如果有不清楚的地方,请随时告诉我。谢谢。

1个回答

3

这里不需要创建一个延迟对象,因为$.post()已经返回了一个Promise对象,而$.when()会按照顺序保存结果。你可以这样做:

$.when.apply($, _arrOfUsers.map(function(user) {
    return $.post("//sessionID", queryServ.getAllUserDomainCommentsFunc("//currentDomainID", user.iD, "//currentDomainID", "//currentURL"));
})).then(function() {
    // all results available in order here as arguments to this callback
    // arguments[0][0] is the first result
    // arguments[1][0] is the second result
    // arguments[2][0] is the third result and so on 
    for (var i = 0; i < arguments.length; i++) {
        // arguments[i][0] is next one  of your results
    }
});

注意:我并不完全理解您尝试在$.post()中使用参数的目的(您似乎编造了一些jQuery文档中没有显示的参数),因此我进行了一些简化,但您可能需要调整这些$.post()参数以适应您的目的。
个人而言,我厌恶$.when()及其与jQuery ajax承诺的交互方式(非常难以使用),因此我会将ajax承诺转换为ES6承诺,并使用Promise.all()(如果需要较旧的浏览器支持,则可以使用Bluebird来支持承诺)。
Promise.all(_arrOfUsers.map(function(user) {
    return Promise.resolve($.post("//sessionID", queryServ.getAllUserDomainCommentsFunc("//currentDomainID", user.iD, "//currentDomainID", "//currentURL")));
})).then(function(results) {
    // results is an array of results in order
});

或者如果你包含了Bluebird,你可以使用:

Promise.map(_arrOfUsers, function(user) {
    return Promise.resolve($.post("//sessionID", queryServ.getAllUserDomainCommentsFunc("//currentDomainID", user.iD, "//currentDomainID", "//currentURL")));
}).then(function(results) {
    // results is an array of results in order
});

感谢您的评论jfriend00,我会尽快尝试您的代码。无论如何,我添加了这些参数是因为我尝试保留$.ajax(url [,settings])的所有参数..但是我不确定是否正确! - nicoperillo
@nicoperillo - 如果你要将所有这些参数传递给 $.post(),你必须将它们放入一个对象中并传递该对象。 - jfriend00

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接