我能找到的最接近的答案是https://stackoverflow.com/a/17216555/2834734
.then最常见的用途是链接ajax请求:
$.ajax({...}).then(function(){ return $.ajax({...}); }).then(function(){ return $.ajax({...}); }).then(function(){ return $.ajax({...}); }).then(function(){ return $.ajax({...}); });
这可以在循环中轻松完成
然而,这是循环过程我遇到困难加上我有一些不寻常的情况。
一个简短的解释是,我有一个需要循环的请求数组,有些会调用ajax加载而有些则不会。我需要它们连续运行,但也会在当时运行特定的函数调用。
这是我的情况的简单(我希望)样本:
// Here is my flow of logic
var thingsToDo = new tasks(); // Initiate the constructor, explained below
// Loop through the requests array and process them consecutively
for (var i in thingsToDo.requests) {
$.when(thingsToDo.jqxhr).then(function() {
thingsToDo.requests[i].fn();
})
}
// Run my final function at the end of the chain.
$.when(thingsToDo.jqxhr).then(function() {
runOnceAllComplete();
});
这是上面的构造函数类。
// Constructor
function tasks() {
_tasks_ = this; // automatic global var
this.jqxhr = undefined; // Var to monitor ajax calls
this.requests = [ // list of tasks to run.
{
url: 'file1.php',
fn: function() {
_tasks_.load(this.url);
console.log('file1 loaded');
}
}, {
url: 'file2.php',
fn: function() {
_tasks_.load(this.url);
console.log('file2 loaded');
}
}, {
noUrl: true, // Note there is no file to load here
fn: function() {
console.log('no file here to load, but process something else');
$('body').css("background-color", "blue");
}
}, {
url: 'file3.php',
fn: function() {
_tasks_.load(this.url);
console.log('file1 loaded');
}
},
];
this.load = function(file) { // This runs the ajax call and resets this.jqxhr
this.jqxhr = $.get(file);
}
}
function runOnceAllComplete() {
alert('hooray!, we finished');
}
我所遇到的棘手部分是请求是动态创建的,因此可以执行1-n个请求,这就是我选择循环的原因,并且必须按顺序执行。
如上所述,一些请求会调用ajax调用,而其他请求可能不会调用$.when().then()
,但问题是循环在promise解析之前继续,并且我的最终函数在最终函数之前发生请求。
我还是第一次尝试使用它们时仍然试图理解承诺。
答案 0 :(得分:1)
尝试在return
,fn
添加this.load
声明;在.promise()
处将$("body")
链接到fn
以返回jQuery promise对象;在Function.prototype.apply()
$.map()
,$.when()
fn: function() {
// added `return`
return _tasks_.load(this.url);
}
this.load = function(file) {
this.jqxhr = $.get(file);
// added `return`
return this.jqxhr
}
fn: function() {
console.log('no file here to load, but process something else');
// added `return` , `.promise()`
return $('body').css("background-color", "blue").promise();
}
$.when.apply($, $.map(thingsToDo.requests, function(task) {
return task.fn()
})).then(runOnceAllComplete)
另请参阅Pass in an array of Deferreds to $.when(),What does $.when.apply($, someArray) do?
但是我遇到了问题,使用.map()它不会等待 在处理下一个请求之前完成每个请求。我需要 每一个都要在移动到下一个之前完成。
尝试使用.queue()
,它将按顺序调用队列中的函数,并且仅在当前函数调用next
时
$(thingsToDo).queue("tasks", $.map(thingsToDo.requests, function(task) {
return function(next) {
// call next function in `"tasks"` queue
// when current function completes using `.then(next)`
return task.fn().then(next)
}
})).dequeue("tasks").promise("tasks").then(runOnceAllComplete)