我必须运行一个递归过程,并且承诺不能按我的意愿运行。这是代码:
var openAllLeves = function () {
openAll = 1;
$.when(openLevels()).then(openAll = 0);
}
var openLevels = function () {
var promises = [];
$('.myClass:not([data-type="T"])').each(function () {
var defer = $.Deferred();
$.when(loadLine($(this)).then(promises.push(defer)));
});
return $.when.apply(undefined, promises).promise();
}
var loadLine = function (thisObj) {
var defer = $.Deferred();
switch(nivel) {
case 1:
$.when(getPT($(thisObj).attr('data-a'))).then(defer.resolve());
break;
case 2:
// ...
}
return defer.promise();
}
var getPT = function (psn) {
var defer = $.Deferred();
var payload = { /* parameters... */ };
$.ajax({
url: webmethod,
data: payload,
type: "POST",
contentType: "application/json; charset=utf-8",
dataType: "json",
timeout: 10000,
success: function (data) {
$.when(paintPT(data)).then(function () {
if (openAll)
openLevels(), defer.resolve();
});
}
});
return defer.promise();
}
我的问题是openAll的值在ajax函数成功代码中被评估之前变为0,因此只执行一次迭代并且没有完成递归。看起来像.then是在解析promises数组之前执行的。
代码有点令人困惑,所以任何帮助都表示赞赏。 提前谢谢。
答案 0 :(得分:1)
代码中的一个大问题是,您正在调用然后回调中的函数,而不是将它们传递给它。例如:
.then(defer.resolve());
这样,您将 defer.resolve()的值传递给 then 回调,而不是异步操作完成时应调用的函数。你应该做这样的事情:
.then(defer.resolve.bind(defer));
这同样适用于其余代码。 你应该看一下承诺spec
特别是
如果onFulfilled不是函数,则必须忽略它。
修改强>
正如Bergi所指出的那样,你应该避免推迟反模式。
答案 1 :(得分:1)
此外,当您将某些内容传递给.then()
时,它必须是回调函数,调用promises.push(defer)
,defer.resolve()
和openAll = 0
左右不起作用,它会执行该操作立即表达,而不是等待承诺。
$.when()
和.promise()
来电几乎是多余的。放下它们。
function openAllLeves () {
openAll = 1;
openLevels().then(function() {
openAll = 0
});
}
function openLevels() {
var promises = [];
$('.myClass:not([data-type="T"])').each(function () { // using `map` would be even better
promises.push(loadLine($(this)));
});
return $.when.apply($, promises);
}
function loadLine(thisObj) {;
switch(nivel) {
case 1:
return getPT($(thisObj).attr('data-a'))
case 2:
// ...
}
}
function getPT(psn) {
var payload = { /* parameters... */ };
return $.ajax({
url: webmethod,
data: payload,
type: "POST",
contentType: "application/json; charset=utf-8",
dataType: "json",
timeout: 10000,
}).then(function (data) {
return paintPT(data);
}).then(function () {
if (openAll)
openLevels();
});
}
顺便说一句,您可能希望将if (openAll) openLevels();
链接到openLevels()
的返回值,而不是链接到每个请求承诺。
答案 2 :(得分:0)
感谢您的回复。我正在研究这种变化。这样,我明白.then()只在传递函数时等待promise。因此,在.then()中解决承诺的正确方法是......
.then(function() {
defer.resolve();
})
¿?