等待 jQuery AJAX 响应

18

我有一个页面,使用jQuery .ajax调用100次(async:true),问题是当它们全部加载完成后,我需要系统在继续之前等待所有100个调用都返回。我该怎么做?

谢谢!:)

更新:

这些调用是在for()循环中完成的(总共有100个:))


1
这些是单独的ajax()调用还是一个调用,其中您更改了请求URL? - Matthew Riches
2
我认为 https://dev59.com/kVfUa4cB1Zd3GeqPMelz 上的解决方案可能适用于你。 - Niklas
Matthew Riches:好几个。Niklas:谢谢:) 我会去看看的! - Olive
5个回答

36

使用 $.when 是更好的方法。您可以按如下方式使用:

$.when(
    $.ajax({/*settings*/}),
    $.ajax({/*settings*/}),
    $.ajax({/*settings*/}),
    $.ajax({/*settings*/}),
).then(function() {
    // when all AJAX requests are complete
});

或者,如果你把所有的AJAX调用都放在一个数组里,那么你可以使用apply

$.when.apply($, ajaxReqs);

请注意,这需要至少jQuery 1.5。


要将AJAX请求添加到数组中,请执行以下操作:

var ajaxReqs = [];
for (var i = 0; i < 100; i++) {
    ajaxReqs.push($.ajax({
        /* AJAX settings */
    });
}
$.when.apply($, ajaxReqs).then(function() {
    // all requests are complete
});

2
啊啊啊...就在你认为你已经掌握了jQuery的时候,又出现了新的东西。 - Salman A
我可以问一下吗?我的“100”循环在另一个更大的循环内部,这会在等待Ajax时暂停更大的循环还是继续执行? :) - Olive
我该如何暂停它呢? - Olive
重构你的代码,使需要延迟执行的代码放在“then”回调函数中。拥抱异步编程! - lonesomeday
1
绝妙的答案。满分。 - Tom Beech
显示剩余3条评论

4
这种问题在数据库SQL设计中无处不在,虽然它不完全相同,但这个问题正是会让你受到影响的东西:网络通信。
你需要注意这一点,因为如果你不正确处理,它会回来咬你——也就是说,用户将会非常生气地等待。我无法强调这一点的重要性。
以下是场景描述: 你想在请求时从服务器传输许多小段信息。 每个请求都依赖于多个因素的高效操作,而所有这些因素都不在你的控制之下:
Wide area Network reposnse time (anywhere in the world right?)
Locak area Network reposnse time (anywhere in the building)
WebServer Load
WebServer Response time
Database response time
Backend Script run time
Javascript run time to process the result
The fact that the browsers are generally limited to 6-8 parallel AJAX requests at once (I think - someone correct me on the exact number)

将请求乘以(嗯...在您的情况下乘以100)。

明白了吗?

在本地机器上测试可能会非常顺利。您甚至可以在完全相同的机器上运行自己的数据库和Web服务器...但在实际应用中尝试这样做,不久你就会遇到可靠性问题。

听着,最简单的方法是将所有参数都包装到一个JS数组中,并将其作为一个POST请求发送。然后在服务器端执行所有数据库选择,并将响应汇总到一个JSON/XML响应中。

此时,您只需等待一个AJAX响应。您可以在JSON/XML结果中找到所有数据。

考虑到您正在处理100个请求,您可能能够使用秒表实际测量时间节省!

相信我 - 尽可能少地进行网络请求。


1
非常感谢您提供如此详细的答案 :)然而,(总有这样的情况,不是吗?)我正在使用AJAX的不是实际的数据库,而是一个页面,用于从特定网站上获取信息。 因此,我不能一次性进行所有100个请求,或者说,我可以,但那需要几个小时(我进行了秒表测试;))。而当使用jQuery+Ajax运行时,只需要几分钟 :)再次感谢! - Olive
我不确定你是如何在几个小时内成功获取了一个网页?我之前使用 CURL 获取页面元数据也是同样的操作。这个过程只需要获取页面所需的时间,所以你一定是做错了什么。 - T9b

3
您可以使用延迟对象API。只要$.ajax返回延迟对象,您可以尝试以下代码来使用循环:
var ajaxes = [];
for (i = 1; i < 100; i++) {
  ajaxes[i] = $.ajax({/*data*/});
}

$.when.apply( ajaxes )
   .then(function(){
      console.log( 'I fire once all ajax requests have completed!' );
   })
   .fail(function(){
      console.log( 'I fire if one or more requests failed.' );
   });

PS:Eric Hynds撰写了一篇关于jQuery 1.5中如何使用延迟对象的优秀文章,您可以阅读Using Deferreds in jQuery 1.5


我更新了主要问题,如果我在一个for循环中进行所有Ajax调用,我还能使用你的方法吗? - Olive
1
这样行不通。如果你传递给 $.when 的不是一个 Deferred 对象(包括包含 Deferred 对象的数组),它会立即返回。你需要使用我的答案中提到的 $.when.apply 来解决这个问题。 - lonesomeday
谢谢!你说得对,我漏掉了它。 - Pavel Morshenyuk

2

需要发起100次Ajax调用?这似乎是一个非常奇怪的需求,而您想要实现的目标很可能可以使用其他方法来实现:

var i = 0;
function myCallback() { alert('已完成100次'); }
function doAjax() { $.ajax({ url: 'blah.php', data: 'hello=world', success: function(response) { i++; }, complete: function() { if(i < 100) { doAjax(); } else { myCallback(); } } }); }
doAjax(); // 开始

我知道这很奇怪 :) 我应该补充说明每个调用都不同,并且我需要所有返回的数据.. - Olive
每个调用有什么不同之处?不同的终端URL?不同的数据?很容易操作我的答案以允许这样做,并将返回的数据存储在另一个变量中,然后发送到回调函数。 - amustill
不同的数据 :) 但我想这归根结底是一样的东西,只需要更改数据即可。 - Olive

0
我不是JS专家,但我会创建一个全局变量作为计数器,并定义一个定时函数来定期检查这个全局变量是否达到了100。
编辑:setTimeout()

什么是定时函数? :) - Olive
2
算了吧,我看你会得到更好的解决方案。 - Damien

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接