链接jquery .when()。then()在一个固定的链调用结束的循环中

我能找到的最接近的答案是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解决之前继续,并且我的最终函数发生在最后的要求。 仍然试图让我的头脑绕过承诺,这是我第一次使用它们。

尝试在fnthis.load包含return语句; 在fn处添加.promise()链接到$("body")以返回jQuery promise对象; 在$.when()使用Function.prototype.apply()$.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) 

另请参见将Deferred数组传递给$ .when() , $ .when.apply($,someArray)做什么?


但是我遇到了一个问题,使用.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) 

请参阅.queue() .promise() , 在javascript中执行函数队列