【问题标题】:jQuery - wait for all nested ajax and each calls to completejQuery - 等待所有嵌套的 ajax 和每个调用完成
【发布时间】:2018-03-14 23:56:32
【问题描述】:

在继续之前,我似乎无法让这段 JavaScript 运行完成。 ajax 内部有一个 each,它本身就在 ajax 的一个 each 内部。

每次我在 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();
}

【问题讨论】:

  • 我怀疑这是因为promises 数组在代码到达SetupHtmlDivs 底部时为空,因为第一个ajax 调用尚未触发。

标签: jquery ajax jquery-deferred


【解决方案1】:

尝试以下方法:

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 调用中不需要promise,因为这是success 回调中的非ajax 操作。它只需要解决它自己提供的单一承诺。
  • 外部函数SetupHtmlDivs 只需要一个promise,当所有生成的内部promise 都完成时,该promise 就会被解析。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-05-04
    • 1970-01-01
    • 2013-08-10
    • 2014-05-30
    • 2015-08-15
    • 2014-05-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多