jQuery - 等待所有嵌套的 ajax 和每个调用完成
jQuery - wait for all nested ajax and each calls to complete
在继续之前,我似乎无法完成 JavaScript 到 运行 的这一点。在 ajax 中有一个 each,它本身在 ajax.
的 each 内部
每次我在 Chrome 中加载它(并在我的评论 "I don't want this to happen until..." 处设置一个断点),它会在我的 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();
}
尝试以下操作:
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 调用中不需要承诺,因为这是 success
回调中的 non-ajax 操作。它只需要解决它自己提供的单一承诺。
- 外部函数
SetupHtmlDivs
只需要一个 promise,当所有生成的内部 promise 都完成时,该 promise 就会被解析。
在继续之前,我似乎无法完成 JavaScript 到 运行 的这一点。在 ajax 中有一个 each,它本身在 ajax.
的 each 内部每次我在 Chrome 中加载它(并在我的评论 "I don't want this to happen until..." 处设置一个断点),它会在我的 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();
}
尝试以下操作:
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 调用中不需要承诺,因为这是success
回调中的 non-ajax 操作。它只需要解决它自己提供的单一承诺。 - 外部函数
SetupHtmlDivs
只需要一个 promise,当所有生成的内部 promise 都完成时,该 promise 就会被解析。