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

时间:2015-12-28 06:52:45

标签: javascript jquery ajax

我能找到的最接近的答案是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解析之前继续,并且我的最终函数在最终函数之前发生请求。 我还是第一次尝试使用它们时仍然试图理解承诺。

1 个答案:

答案 0 :(得分:1)

尝试在returnfn添加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)

请参阅.queue().promise()Execute function queue in javascript