等到for循环中的所有Ajax请求都完成后再继续吗?

时间:2019-05-31 16:52:05

标签: javascript ajax asynchronous

我必须调用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();
        });
};

2 个答案:

答案 0 :(得分:1)

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

如果您似乎无法做到这一点,我已经研究了一种在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等...],然后使用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/

答案 1 :(得分:0)

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

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

尝试在$.wait函数内部调用suitesJSON.done,这样将在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();
        });
    });
};