如何让函数等待所有 jQuery Ajax 请求在另一个函数内完成?
简而言之,在执行下一个请求之前,我需要等待所有 Ajax 请求完成。但是如何?
如何让函数等待所有 jQuery Ajax 请求在另一个函数内完成?
简而言之,在执行下一个请求之前,我需要等待所有 Ajax 请求完成。但是如何?
jQuery 现在为此定义了一个when 函数。
它接受任意数量的 Deferred 对象作为参数,并在它们全部解析时执行一个函数。
这意味着,如果您想发起(例如)四个 ajax 请求,然后在完成后执行一个操作,您可以执行以下操作:
$.when(ajax1(), ajax2(), ajax3(), ajax4()).done(function(a1, a2, a3, a4){
// the code here will be executed when all four ajax requests resolve.
// a1, a2, a3 and a4 are lists of length 3 containing the response text,
// status, and jqXHR object for each of the four ajax calls respectively.
});
function ajax1() {
// NOTE: This function must return the value
// from calling the $.ajax() method.
return $.ajax({
url: "someUrl",
dataType: "json",
data: yourJsonData,
...
});
}
在我看来,它提供了干净清晰的语法,并避免涉及任何全局变量,例如 ajaxStart 和 ajaxStop,这可能会在您的页面开发过程中产生不必要的副作用。
如果您事先不知道需要等待多少个 ajax 参数(即您想使用可变数量的参数),它仍然可以完成,但只是有点棘手。请参阅将延迟数组传递给 $.when()(也可能是jQuery .when 使用可变数量的参数进行故障排除)。
如果您需要更深入地控制 ajax 脚本等的失败模式,您可以保存返回的对象.when()
- 它是一个包含所有原始 ajax 查询的 jQuery Promise对象。您可以调用.then()
或.fail()
来添加详细的成功/失败处理程序。
如果您想知道文档中的所有 ajax
请求何时完成,无论存在多少个请求,只需以$.ajaxStop
这种方式使用事件:
$(document).ajaxStop(function () {
// 0 === $.active
});
在这种情况下,您既不需要猜测应用程序中发生了多少请求,这些请求可能在未来完成,也不需要深入研究函数的复杂逻辑或找出哪些函数正在执行
HTTP(S)
请求。
$.ajaxStop
here 也可以绑定到HTML
您认为可能会被请求修改的任何节点。
更新:
如果你想坚持使用ES
语法,那么你可以使用Promise.all
已知ajax
方法:
Promise.all([ajax1(), ajax2()]).then(() => {
// all requests finished successfully
}).catch(() => {
// all requests finished but one or more failed
})
这里有趣的一点是它同时适用于Promises
和$.ajax
请求。
这是jsFiddle演示。
更新 2:
使用async/await语法的更新版本:
try {
const results = await Promise.all([ajax1(), ajax2()])
// do other actions
} catch(ex) { }
我通过gnarf my self找到了一个很好的答案,这正是我正在寻找的 :)
jQuery ajax队列
//This handles the queues
(function($) {
var ajaxQueue = $({});
$.ajaxQueue = function(ajaxOpts) {
var oldComplete = ajaxOpts.complete;
ajaxQueue.queue(function(next) {
ajaxOpts.complete = function() {
if (oldComplete) oldComplete.apply(this, arguments);
next();
};
$.ajax(ajaxOpts);
});
};
})(jQuery);
然后你可以像这样向队列添加一个ajax请求:
$.ajaxQueue({
url: 'page.php',
data: {id: 1},
type: 'POST',
success: function(data) {
$('#status').html(data);
}
});
使用ajaxStop
事件。
例如,假设您在获取 100 个 ajax 请求时有一个loading...消息,并且您想在加载后隐藏该消息。
从 jQuery文档:
$("#loading").ajaxStop(function() {
$(this).hide();
});
请注意,它将等待该页面上完成的所有 ajax 请求。
注意:上述答案使用的功能在编写此答案时尚不存在。我建议使用jQuery.when()
而不是这些方法,但我将答案留给历史目的。
——
您可能可以使用简单的计数信号量来解决问题,尽管您如何实现它取决于您的代码。一个简单的例子是这样的......
var semaphore = 0, // counting semaphore for ajax requests
all_queued = false; // bool indicator to account for instances where the first request might finish before the second even starts
semaphore++;
$.get('ajax/test1.html', function(data) {
semaphore--;
if (all_queued && semaphore === 0) {
// process your custom stuff here
}
});
semaphore++;
$.get('ajax/test2.html', function(data) {
semaphore--;
if (all_queued && semaphore === 0) {
// process your custom stuff here
}
});
semaphore++;
$.get('ajax/test3.html', function(data) {
semaphore--;
if (all_queued && semaphore === 0) {
// process your custom stuff here
}
});
semaphore++;
$.get('ajax/test4.html', function(data) {
semaphore--;
if (all_queued && semaphore === 0) {
// process your custom stuff here
}
});
// now that all ajax requests are queued up, switch the bool to indicate it
all_queued = true;
如果您希望它像 {async: false} 一样操作,但又不想锁定浏览器,则可以使用 jQuery 队列完成相同的操作。
var $queue = $("<div/>");
$queue.queue(function(){
$.get('ajax/test1.html', function(data) {
$queue.dequeue();
});
}).queue(function(){
$.get('ajax/test2.html', function(data) {
$queue.dequeue();
});
}).queue(function(){
$.get('ajax/test3.html', function(data) {
$queue.dequeue();
});
}).queue(function(){
$.get('ajax/test4.html', function(data) {
$queue.dequeue();
});
});