我如何让一个函数等待,直到所有的jQuery Ajax请求在另一个函数内完成?

简而言之,在执行下一个Ajax请求之前,我需要等待所有Ajax请求都完成。但如何?


当前回答

如果从头开始,我强烈建议使用$.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>

其他回答

如果从头开始,我强烈建议使用$.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>

我找到了一个很好的答案,这正是我在寻找的:)

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);
        }
    });

美元。当不为我工作时,回调(x)而不是返回x工作如下所述:https://stackoverflow.com/a/13455253/10357604

当所有ajax加载完成时,我使用大小检查

function get_ajax(link, data, callback) { $.ajax({ url: link, type: "GET", data: data, dataType: "json", success: function (data, status, jqXHR) { callback(jqXHR.status, data) }, error: function (jqXHR, status, err) { callback(jqXHR.status, jqXHR); }, complete: function (jqXHR, status) { } }) } function run_list_ajax(callback){ var size=0; var max= 10; for (let index = 0; index < max; index++) { var link = 'http://api.jquery.com/ajaxStop/'; var data={i:index} get_ajax(link,data,function(status, data){ console.log(index) if(size>max-2){ callback('done') } size++ }) } } run_list_ajax(function(info){ console.log(info) }) <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script>

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()来添加详细的成功/失败处理程序。