我如何让一个函数等待,直到所有的jQuery Ajax请求在另一个函数内完成?
简而言之,在执行下一个Ajax请求之前,我需要等待所有Ajax请求都完成。但如何?
我如何让一个函数等待,直到所有的jQuery Ajax请求在另一个函数内完成?
简而言之,在执行下一个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参数(即你想使用可变数量的参数),它仍然可以完成,只是有点棘手。参见在一个数组中传递deferred to $.when()(也可以是jQuery .当使用可变参数进行故障排除时)。
如果你需要更深入地控制ajax脚本的失败模式等,你可以保存.when()返回的对象-它是一个包含所有原始ajax查询的jQuery承诺对象。您可以调用.then()或.fail()来添加详细的成功/失败处理程序。
其他回答
Javascript是基于事件的,所以你不应该等待,而应该设置钩子/回调
你可以只使用jquery.ajax的success/complete方法
或者你可以使用。ajaxcomplete:
$('.log').ajaxComplete(function(e, xhr, settings) {
if (settings.url == 'ajax/test.html') {
$(this).text('Triggered ajaxComplete handler.');
//and you can do whatever other processing here, including calling another function...
}
});
虽然你应该张贴一个伪代码你的(s) ajax请求(s)是(是)被调用更精确…
如果你需要简单的东西;Once and done回调
//multiple ajax calls above
var callback = function () {
if ($.active !== 0) {
setTimeout(callback, '500');
return;
}
//whatever you need to do here
//...
};
callback();
我找到了一个很好的答案,这正是我在寻找的:)
jQuery ajaxQueue
//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);
}
});
我的解决方案如下
var request;
...
'services': {
'GetAddressBookData': function() {
//This is the primary service that loads all addressbook records
request = $.ajax({
type: "POST",
url: "Default.aspx/GetAddressBook",
contentType: "application/json;",
dataType: "json"
});
},
...
'apps': {
'AddressBook': {
'data': "",
'Start': function() {
...services.GetAddressBookData();
request.done(function(response) {
trace("ajax successful");
..apps.AddressBook.data = response['d'];
...apps.AddressBook.Filter();
});
request.fail(function(xhr, textStatus, errorThrown) {
trace("ajax failed - " + errorThrown);
});
工作得很顺利。我已经尝试了许多不同的方法,但我发现这是最简单和最可重用的方法。希望能有所帮助
如果从头开始,我强烈建议使用$.when()。
尽管这个问题有超过一百万个答案,但我仍然没有找到任何对我的情况有用的答案。假设您必须处理现有的代码库,已经进行了一些ajax调用,并且不想引入承诺的复杂性和/或重做整个事情。
我们可以很容易地利用jQuery的.data, .on和.trigger函数,这些函数一直是jQuery的一部分。
Codepen
我的解决方案的优点是:
显然回调依赖于什么 函数triggerNowOrOnLoaded并不关心数据是否已经加载或我们仍在等待它 将其插入现有代码非常容易
$(function() { // wait for posts to be loaded triggerNowOrOnLoaded("posts", function() { var $body = $("body"); var posts = $body.data("posts"); $body.append("<div>Posts: " + posts.length + "</div>"); }); // some ajax requests $.getJSON("https://jsonplaceholder.typicode.com/posts", function(data) { $("body").data("posts", data).trigger("posts"); }); // doesn't matter if the `triggerNowOrOnLoaded` is called after or before the actual requests $.getJSON("https://jsonplaceholder.typicode.com/users", function(data) { $("body").data("users", data).trigger("users"); }); // wait for both types triggerNowOrOnLoaded(["posts", "users"], function() { var $body = $("body"); var posts = $body.data("posts"); var users = $body.data("users"); $body.append("<div>Posts: " + posts.length + " and Users: " + users.length + "</div>"); }); // works even if everything has already loaded! setTimeout(function() { // triggers immediately since users have been already loaded triggerNowOrOnLoaded("users", function() { var $body = $("body"); var users = $body.data("users"); $body.append("<div>Delayed Users: " + users.length + "</div>"); }); }, 2000); // 2 seconds }); // helper function function triggerNowOrOnLoaded(types, callback) { types = $.isArray(types) ? types : [types]; var $body = $("body"); var waitForTypes = []; $.each(types, function(i, type) { if (typeof $body.data(type) === 'undefined') { waitForTypes.push(type); } }); var isDataReady = waitForTypes.length === 0; if (isDataReady) { callback(); return; } // wait for the last type and run this function again for the rest of the types var waitFor = waitForTypes.pop(); $body.on(waitFor, function() { // remove event handler - we only want the stuff triggered once $body.off(waitFor); triggerNowOrOnLoaded(waitForTypes, callback); }); } <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <body>Hi!</body>