2011-11-11 67 views
5

我正在使用jQuery,并且有一个异步AJAX请求循环。我知道我可以通过使用方便的'$ .when.apply(array_of_requests).then()'方法等待它们全部完成。如何等待,直到嵌套异步jQuery AJAX请求已完成?

但我也有另一套AJAX请求,只在每个第一个请求完成后才执行。我想等他们完成,但我不是100%确定我找到了最好的方法。

这里是我的请求,一个简单的例子:

var intital_data = [1,2,3,4,5,6,7,8,9,10]; 
var promises = []; 
var promises_inner = []; 

$.each(intitial_data, function(i, n) { 
    var ajax_call = $.ajax({url:'http://www.domain.com/etc/'+n}); 
    promises.push(ajax_call); 

    ajax_call.done(function(data) { 
     var ajax_call_inner = $.ajax({url:'http://www.domain.com/etc/'+data.result}); 
     promises_inner.push(ajax_call_inner); 

     ajax_call_inner.done(function(data) { 
      // Do something with the content of data here. 
     }); 
    }); 
}); 

所以,当每个十环AJAX请求完成后,我做基于第一结果的第二AJAX请求。这一切都很好。

我再有这样的事情,因为我要等到双方的前十个请求(存储的承诺阵列)第二批(存储在promises_inner)完成:

$.when.apply($, promises).then(
    function() { 
     // The ten outer AJAX calls are finished now. 

     $.when.apply($, promises_inner).then(
      function() { 
       // The inner AJAX calls are finished now. 
      } 
     ); 
    } 
); 

在第一个$ .when.apply()。then()的'done'函数中,第二批请求还没有完成,甚至还没有添加到promises_inner数组中。但我发现添加一个嵌套的$ .when.apply()。then()似乎工作 - 在其“完成”功能全部请求已完成。

但我不确定这是最好的,最健壮的解决方案。我担心它只能在巧合的情况下工作 - 它只会导致电话完成的延迟 - 而不是合乎逻辑的意义。

有更好的,更坚固的解决方案吗?谢谢。

+0

我很快就谈到过,当我说,它似乎工作。有时,它的工作原理,但其他时候,promises_inner一直没有所有的嵌套的AJAX查询广告还没有。所以有时候内部的$ .when发生在所有的东西都被返回之前。 –

回答

2

看看1.7中的$ .Callbacks。我认为你会对制作自己的“流量”的灵活性以及重用它们的能力感到兴奋,只需运行一次等等。

你做了什么没有问题(应用模式可能不是第一选择大多数情况下,他们通常只是在$ .when(a,b,c ....)中列出它们 - 但是您可能更喜欢$ .Callbacks的语法。

+0

感谢您的指针。 $ .Callbacks文档让我的大脑受到伤害,但我希望它最终会沉入其中!与此同时,你认为我的嵌套$ .when应该是可靠的吗? –

+0

在我们的保险应用程序中处理规则时,我们必须做类似的事情,因为至少涉及10个服务。你可以做的更容易阅读的另一件事是创建一个Deferred,并且只在第一个完成时解析它。将Deferred的承诺用作下一组回调的.done。 Addy Osmani在回调方面有很好的文章,可能还会有更多。 – AutoSponge

0

试试这个只有一个主要承诺fullfill(解析)每个循环运行(这里仍称inner_promise)。

var initial_data = [1,2,3,4,5,6,7,8,9,10]; 
var promises_inner = []; 

initial_data.forEach(function(n) { 
    // Create promise for the inner call here. 
    var promise_inner = $.Deferred(); 
    promises_inner.push(promise_inner); 

    $.ajax({url:'http://www.domain.com/etc/'+n}).done(function(data) { 
     $.ajax({url:'http://www.domain.com/etc/'+data.result}).done(function(data) { 
      // Do something with the content of data here. 
      promise_inner.resolve(); 
     }); 
    }); 
}); 
console.log("promises_inner contains " + promises_inner.length + " promises") // should contain all the 10 promises 

$.when.apply($,promises_inner).done(function() { 
    // The inner AJAX calls are finished now 
})