协慌网

登录 贡献 社区

等到所有 jQuery 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 参数(即,您想使用可变数量的参数),它仍然可以完成,但是有点棘手。请参阅将 Deferreds 数组传递给 $ .when() (以及在使用可变数量的参数进行故障排除时,可能还有 jQuery。)。

如果您需要对 ajax 脚本等的失败模式进行更深入的控制,则可以保存.when()返回的对象 - 这是一个 jQuery Promise对象,包含所有原始 ajax 查询。您可以在其上调用.then().fail()来添加详细的成功 / 失败处理程序。

如果您想知道文档中所有ajax请求何时完成,无论它们存在多少,只需使用$ .ajaxStop事件以这种方式:

$(document).ajaxStop(function () {
  // 0 === $.active
});

在这种情况下,您既无需猜测应用程序中正在发生的请求数量(可能在将来完成),也无需深入研究复杂逻辑的功能或查找正在执行HTTP(S)请求的功能。

$.ajaxStop也可以绑定到您认为可能被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找到了一个很好的答案,这正是我想要的东西:)

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