我有多个ajax查询同时运行,我希望它们等待最后一个返回,然后在所有ajax调用上运行成功处理程序。作为简化示例,请考虑:
$.ajax({//ajax call 1 url:page1.php, success: function(data1){ //do something with data1 } }); .... $.ajax({//ajax call 2 url:page2.php, success: function(data2){ //do something with data2 } }); //consider more than just two concurrent requests
假设所有请求都同时发送。由于它们是异步的,因此它们将在不同的时间返回。假设一个请求返回需要100毫秒,而另一个请求则需要3000毫秒。我显然不知道哪个会最先返回。他们都以某种方式更新了DOM,我希望一次将这些更改一次全部显示给查看器。我该怎么做呢?
我能想到的最好的方法是将data1和data2保存为全局变量。然后有一个计数器变量,该变量在每次返回成功时都进行计数。然后,在counter == TOTAL_NUM_REQUESTS处调用一个诸如updateAll()之类的函数,然后遍历所有全局变量并将其放在需要的地方。但是,这似乎很混乱并且容易出错。加上那将是很多全局变量。
我理想的情况是让成功处理程序在返回时进入睡眠状态,然后在我将所有返回值都计为返回值的条件下,向所有返回发送唤醒消息,使它们可以继续执行。这似乎是最干净的方法,但是我不了解javascriptland中的类似功能。
有人对此有任何巧妙的想法吗?
答案更新
感谢下面的Lee,我得以找到解决方案。我的解决方案与下面的类似。我建立了async分配给$ .ajax调用的变量列表。最初,这些ajax调用的成功处理程序仍在被调用,因此我将它们删除,并将它们放在另一个函数中,该函数随后由when我编写的此块调用。我传入results了这样的函数:
async
when
results
var results = []; results.push(async1); results.push(async2); ... for all the results ... $.when.apply(this, results).done(function() { for(var i=0;i<arguments.length;i++){ dataobject=arguments[i][0] if(dataobject.variousattribute) mySuccessHandlerFirstGuy(dataobject) else if(dataobject.anotherattribute) mySuccessHandlerSecondGuy(dataobject) //etc .... } };
arguments对象花了点工夫弄清楚它是什么。这是一个二维数组(列表列表)。第一个索引表示与给定的ajax请求相对应的返回对象。这 似乎 是有序的,但是最好让您的服务器返回您可以查找的内容,并相应地编写一个if / else块。然后,在该给定元素中,该列表中似乎有3个元素。第一个是从服务器返回的值,即所需的值。第二个始终是字符串success,您可以大概使用它来检查调用是否有效。该列表中的第三个元素似乎是初始请求(尽管我不确定)。这对我没有用。
success
无论如何,我希望这对将来的人有所帮助。再次感谢李向我指出正确的方向。
当所有ajax调用结束时,使用jQuery $ .when()函数运行某些内容:
jQuery.when文档
var async1 = $.ajax({//ajax call 1 url:page1.php, success: function(data1){ //do something with data1 } }); .... var async2 = $.ajax({//ajax call 2 url:page2.php, success: function(data2){ //do something with data2 } }); $.when(async2, async1).done(function(result2, result1) { ... do this when both are successful ... });
在回答问题时添加:
如果您有一堆ajax调用,则可以使用“ apply”,如下所示:
var results = []; results.push(async1); results.push(async2); ... for all the results ... $.when.apply(this, results).done(function() { ... use 'arguments' array to get results ... });