jQuery - 等待所有嵌套的ajax并完成每个调用

时间:2018-03-14 23:56:33

标签: jquery ajax jquery-deferred

在继续之前,我似乎无法让这些JavaScript运行完成。 ajax中的每一个都位于ajax的内部。

每次我在Chrome中加载它(并设置一个断点,我的评论说"我不希望这种情况发生在..."),它会在我的断点之前到达我的断点htmlDivs集合中有任何内容。继续之后,htmlDivs集合总是被填满,这让我相信我在尝试使用promises和.done()时做错了。

代码最好地说明了这一点:

var htmlDivs = {};

function SelectTopLevelThingFromPage(id) {
    SetupHtmlDivs(id).done(
        function () {
            // I don't want this to happen until SetupHtmlDivs() completes
            // (including all nested $.each and $.ajax)
            var keys = Object.keys(htmlDivs);
            // Append the htmlDivs in a specific sorted order
        }
    );
}

function SetupHtmlDivs(id) {
    var promises = [];

    $.ajax({
        url: "api/GetSecondLevelThingsFromTopLevelId" + id,
        method: "get",
        success: function (SecondLevelThings) {
            $.each(SecondLevelThings, function (i, SecondLevelThing) {
                var promise = SetupHtmlForOneThing(SecondLevelThing);
                promises.push(promise);
            });
        }
    });

    return $.when.apply($, promises).promise();
}

function SetupHtmlForOneThing(SecondLevelThing) {
    var promises = [];

    $.ajax({
        url: "api/SecondLevelThing/" + SecondLevelThing.id + "/Environments",
        method: "get",
        success: function (Environments) {
            $.each(Environments, function (k, env) {
                var def = new $.Deferred();
                promises.push(def);
                htmlDivs[SecondLevelThing.id + "-" + env] = SecondLevelThing;
                def.resolve();
            });
        }
    });

    return $.when.apply($, promises).promise();
}

1 个答案:

答案 0 :(得分:0)

尝试以下方法:

var htmlDivs = {};

function SelectTopLevelThingFromPage(id) {
    SetupHtmlDivs(id).done(
        function () {
            // I don't want this to happen until SetupHtmlDivs() completes
            // (including all nested $.each and $.ajax)
            var keys = Object.keys(htmlDivs);
            // Append the htmlDivs in a specific sorted order
        }
    );
}

function SetupHtmlDivs(id) {

    var finalPromise = new $.Deferred();
    $.ajax({
        url: "api/GetSecondLevelThingsFromTopLevelId" + id,
        method: "get",
        success: function (SecondLevelThings) {
            var promises = [];
            $.each(SecondLevelThings, function (i, SecondLevelThing) {
                var promise = SetupHtmlForOneThing(SecondLevelThing);
                promises.push(promise);
            });

            $.when.apply($, promises).then(function() {
                finalPromise.resolve();
            });
        }
    });

    return finalPromise;
}

function SetupHtmlForOneThing(SecondLevelThing) {
    var innerPromise = new $.Deferred();
    $.ajax({
        url: "api/SecondLevelThing/" + SecondLevelThing.id + "/Environments",
        method: "get",
        success: function (Environments) {
            $.each(Environments, function (k, env) {
                htmlDivs[SecondLevelThing.id + "-" + env] = SecondLevelThing;
            });
            innerPromise.resolve();
        }
    });

    return innerPromise;
}

重大变化是:

  • 内部函数SetupHtmlForOneThing在ajax调用中不需要promises,因为这是success回调中的非ajax操作。它只需要解决自己提供的单一承诺。
  • 外部函数SetupHtmlDivs只需要一个在所有生成的内部promise都完成后得到解决的promise。