【问题标题】:Wait until all Ajax requests in a for loop are done before moving on?等到 for 循环中的所有 Ajax 请求都完成后再继续?
【发布时间】:2019-05-31 16:52:04
【问题描述】:

我必须调用 Agile Central API 以获取缺陷套件列表,然后遍历列表并进行嵌套调用以获取每个套件中的缺陷列表,嵌套调用取决于外部调用.然后我必须将数据行附加到表中,然后调用 doneCallback() 来表示数据收集结束。我遇到的问题是在请求完成之前调用了 doneCallback(),因此实际上并没有传递任何数据

我已经尝试了这篇文章中的方法:Wait until all jQuery Ajax requests are done? 和这篇文章:how to wait until Array is filled (asynchronous)。在控制台中,我可以看到我想要的所有数据都在那里,但没有附加任何数据。我的问题是:如何确保在循环中发出的所有请求都完成并推送数据之前不调用 doneCallback()?这是我现在的代码:

function getSuites() {
        return $.ajax({
            url: suitesURL("71101309592") + "&fetch=Name,FormattedID,Defects",
            type: "GET",
            xhrFields: {
                withCredentials: true
            },
            headers: {
                "zsessionid": apiKey
            }
        });
    }

    function getDefects(_ref) {
        return $.ajax({
            url: _ref,
            type:"GET",
            xhrFields: {
                withCredentials: true
            },
            headers: {
                "zsessionid": apiKey
            }
        });
    }

    // Download the data
    myConnector.getData = function (table, doneCallback) {

        console.log("Getting Data...");

        var ajaxCalls = [], tableData = [];

        var suitesJSON = getSuites();

        suitesJSON.done(function(data) {

            var suites = data.QueryResult.Results;

            for(var i = 0; i < suites.length; i++) {

               (function(i) {
                    var defectsJSON = getDefects(suites[i].Defects._ref + "?fetch=Name,FormattedID,State,Priority,CreationDate,c_RootCause,c_RootCauseCRM");
                    ajaxCalls.push(defectsJSON);

                    defectsJSON.done(function(data) {
                        var defects = data.QueryResult.Results;

                        for(var j = 0; j < defects.length; j++) {
                            tableData.push({
                                "suiteName": suites[i].Name, // This is the name of the suite collected in the outer call
                                "defectName": defects[j].Name,
                                "FormattedID": defects[j].FormattedID,
                                "State": defects[j].State,
                                "Priority": defects[j].Priority,
                                "CreationDate": defects[j].CreationDate,
                                "RootCause": defects[j].c_RootCause,
                                "RootCauseCRM": defects[j].c_RootCauseCRM
                            });
                        }

                    });
               })(i);

            }

        });


        $.when.apply($, ajaxCalls).then(function() {
            console.log(tableData);
            table.appendRows(tableData);
            doneCallback();
        });
};

【问题讨论】:

  • jQuery when() 与 ajax 调用应该没问题....
  • 抱歉,我对使用 ajax 很陌生...请您再解释一下吗?

标签: javascript ajax asynchronous


【解决方案1】:

您应该使用更好的模型来获取多个项目。使用 for 循环查询多个 get 是个问题,解决方案应该是重构,以便您发出一个请求,返回您需要的所有内容。

如果你觉得这不可能,我已经研究了一种在 jQuery 中做你想做的事情的方法。

$.when(
    $.get(path, callback), $.get(path, callback), $.get(path, callback)
.then({
    //This is called after all requests are done
});

您可以创建一个包含所有请求的数组,例如 [$.get(path, callback), request2, request 3, etc...],然后使用 spread 方法将它们作为参数,例如

var args = [$.get(path, callback), request2, request 3, etc...];
$.when(...args).then(() => {/*call here*/});

此链接包含其余信息 https://css-tricks.com/multiple-simultaneous-ajax-requests-one-callback-jquery/

【讨论】:

  • 是的,多次获取不是很好,但问题是每个套件都提供了对套件内部缺陷的 URL 引用,访问这些缺陷的唯一方法是进行另一个 API 调用(据我所知)。不过,我肯定会忽略一些东西
  • 另外,我不是已经用请求(ajaxCalls)填充了一个数组,然后在它们都完成后使用 $.when 调用某些东西吗?还是我没有以正确的方式使用它?在这篇stackoverflow.com/questions/8097516/… 的帖子中,OP 似乎在做与我类似的事情
  • 我根据评论添加了最后一部分 - 我没有意识到它已经在那里了。我会保留答案以帮助将来遇到类似问题的人。
【解决方案2】:

我认为问题在于您在执行 getSuites() 之后立即调用 $.wait

$.wait“看到”ajaxCalls 数组为空(因为getSuites() 尚未完成)并执行doneCallback()

尝试在suitesJSON.done函数内部调用$.wait,这样会在ajaxCalls数组被第一个响应填充后调用:

myConnector.getData = function (table, doneCallback) {
    console.log("Getting Data...");
    var ajaxCalls = [], tableData = [];

    var suitesJSON = getSuites();

    suitesJSON.done(function(data) {

        var suites = data.QueryResult.Results;

        for(var i = 0; i < suites.length; i++) {

           (function(i) {
                var defectsJSON = getDefects(suites[i].Defects._ref + "?fetch=Name,FormattedID,State,Priority,CreationDate,c_RootCause,c_RootCauseCRM");
                ajaxCalls.push(defectsJSON);

                defectsJSON.done(function(data) {
                    var defects = data.QueryResult.Results;

                    for(var j = 0; j < defects.length; j++) {
                        tableData.push({
                            "suiteName": suites[i].Name, // This is the name of the suite collected in the outer call
                            "defectName": defects[j].Name,
                            "FormattedID": defects[j].FormattedID,
                            "State": defects[j].State,
                            "Priority": defects[j].Priority,
                            "CreationDate": defects[j].CreationDate,
                            "RootCause": defects[j].c_RootCause,
                            "RootCauseCRM": defects[j].c_RootCauseCRM
                        });
                    }

                });
           })(i);

        }

        $.when.apply($, ajaxCalls).then(function() {
            console.log(tableData);
            table.appendRows(tableData);
            doneCallback();
        });
    });
};

【讨论】:

  • 这是个好主意,但不幸的是它的行为仍然和以前一样
  • 没关系!这行得通,我只是在进行更改时打错了字。哇我今天脑死了。谢谢!
猜你喜欢
  • 2021-12-27
  • 1970-01-01
  • 2021-08-17
  • 2011-07-21
  • 2021-05-25
  • 2015-07-17
  • 2017-09-07
  • 2020-03-17
相关资源
最近更新 更多