链接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解决之前继续,并且我的最终函数发生在最后的要求。 仍然试图让我的头脑绕过承诺,这是我第一次使用它们。
尝试在fn
, this.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中执行函数队列