等待多个asynchronous调用完成后再继续

所以,我有一个页面加载并通过jquery.get做出几个请求来填充下拉列表的值。

$(function() { LoadCategories($('#Category')); LoadPositions($('#Position')); LoadDepartments($('#Department')); LoadContact(); }; 

然后调用LoadContact(); 哪一个做了另一个调用,当它返回时,它填充表单上的所有字段。 问题是,往往下拉不是全部填充,因此,它不能将它们设置为正确的值。

我需要做的是以某种方式使LoadContact只在其他方法完成且callback完成后才执行。

但是,我不希望在调用LoadContact()之前把一堆标志放在下拉群体callback的最后,然后我再检查,并且必须有一个recursionsetTimeout调用检查。

jQuery中有什么让我说:“当所有这些都完成后执行这个。”?

更多信息我正在思考这方面的事情

 $().executeAfter( function () { // When these are done LoadCategories($('#Category')); LoadPositions($('#Position')); LoadDepartments($('#Department')); }, LoadContact // Do this ); 

…需要跟踪方法执行过程中发生的ajax调用,当它们全部完成时,调用LoadContact;

如果我知道如何拦截正在使用该function的Ajax,我可以写一个jQuery扩展来完成这个function。

我的解决scheme

 ;(function($) { $.fn.executeAfter = function(methods, callback) { var stack = []; var trackAjaxSend = function(event, XMLHttpRequest, ajaxOptions) { var url = ajaxOptions.url; stack.push(url); } var trackAjaxComplete = function(event, XMLHttpRequest, ajaxOptions) { var url = ajaxOptions.url; var index = jQuery.inArray(url, stack); if (index >= 0) { stack.splice(index, 1); } if (stack.length == 0) { callback(); $this.unbind("ajaxComplete"); } } var $this = $(this); $this.ajaxSend(trackAjaxSend) $this.ajaxComplete(trackAjaxComplete) methods(); $this.unbind("ajaxSend"); }; })(jQuery); 

当这个方法被调用的时候,这个绑定到ajaxSend事件上,并且保存一个被调用的url列表( 尽pipe需要一个更好的唯一的id )。 然后它从ajaxSend中解除绑定,所以只跟踪我们关心的请求。 它还会绑定到ajaxComplete,并在返回时从栈中移除项目。 当堆栈达到零时,它执行我们的callback,并解除绑定ajaxComplete事件。

你可以像这样使用.ajaxStop()

 $(function() { $(document).ajaxStop(function() { $(this).unbind("ajaxStop"); //prevent running again when other calls finish LoadContact(); }); LoadCategories($('#Category')); LoadPositions($('#Position')); LoadDepartments($('#Department')); }); 

当所有当前的请求完成后,这将运行,然后解除绑定,如果未来在页面中的Ajax调用执行,它将不会运行。 另外,一定要把它放在你的ajax调用之前,这样它就可以被绑定得更早了,用.ajaxStart()更重要,但是最好用两个方法来做。

扩展Tom Lianza的答案 , $.when() .when $.when()现在比使用.ajaxStop()更好。

唯一需要注意的是,您需要确保在返回Deferred object需要等待的asynchronous方法。 幸运的是,jQuery ajax调用已经在默认情况下做到这一点。 所以为了实现这个问题的场景,需要等待的方法看起来像这样:

 function LoadCategories(argument){ var deferred = $.ajax({ // ajax setup }).then(function(response){ // optional callback to handle this response }); return deferred; } 

然后在所有三个Ajax调用都返回之后调用LoadContact(),并可选地执行各自的callback:

 // setting variables to emphasize that the functions must return deferred objects var deferred1 = LoadCategories($('#Category')); var deferred2 = LoadPositions($('#Position')); var deferred3 = LoadDepartments($('#Department')); $.when(deferred1, deferred2, deferred3).then(LoadContact); 

如果你在JQuery 1.5或更高版本,我怀疑延期对象是你最好的select: http : //api.jquery.com/category/deferred-object/

辅助方法,什么时候也是相当不错的: http : //api.jquery.com/jQuery.when/

但是,我不希望在调用LoadContact()之前把一堆标志放在下拉群体callback的最后,然后我再检查,并且必须有一个recursionsetTimeout调用检查。
不需要setTimeout。 你只需在每个callback中检查所有三个列表是否被填充(或者更好地设置一个计数器,在每个callback中增加它并等到它等于3),然后从callback调用LoadContact。 对我来说似乎很容易。

ajaxStop方法可能工作,我只是不是很熟悉它。