Javascript 等待所有jQuery Ajax请求完成?

Javascript 等待所有jQuery Ajax请求完成?,javascript,jquery,ajax,Javascript,Jquery,Ajax,如何让一个函数等到所有jQueryAjax请求都在另一个函数中完成 简而言之,我需要等待所有Ajax请求完成,然后再执行下一个请求。但是怎么做呢?注意:上述答案使用了在撰写此答案时不存在的功能。我建议使用jQuery.when()而不是这些方法,但我会出于历史目的留下答案 - 您可能只需要使用一个简单的计数信号量,尽管如何实现它取决于您的代码。一个简单的例子是 var semaphore = 0, // counting semaphore for ajax requests

如何让一个函数等到所有jQueryAjax请求都在另一个函数中完成


简而言之,我需要等待所有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();
    });
});
var$queue=$(“”);
$queue.queue(函数(){
$.get('ajax/test1.html',函数(数据){
$queue.dequeue();
});
}).queue(函数(){
$.get('ajax/test2.html',函数(数据){
$queue.dequeue();
});
}).queue(函数(){
$.get('ajax/test3.html',函数(数据){
$queue.dequeue();
});
}).queue(函数(){
$.get('ajax/test4.html',函数(数据){
$queue.dequeue();
});
});

jQuery允许您指定是否希望ajax请求是异步的。您可以简单地使ajax请求同步,然后在它们返回之前,其余代码不会执行

例如:

jQuery.ajax({ 
    async: false,
    //code
});

javascript是基于事件的,所以您不应该等待,而应该设置挂钩/回调

您可能只需要使用

或者您可以使用:

虽然您应该发布一个伪代码,说明如何更准确地调用ajax请求…

我自己找到了一个,这正是我想要的:)

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 f = [
           {file: 'file_path', data: {action: 'action', data: 'any_data}},
           {file: 'file_path', data: {action: 'action', data: 'any_data}},
           {file: 'file_path', data: {action: 'action', data: 'any_data}},
           {file: 'file_path', data: {action: 'action', data: 'any_data}}
        ];
$.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,            
        ...
    });
}
// Define how many Ajax calls must be done
var ajaxCalls = 3;
var counter = 0;
var ajaxCallComplete = function() {
    counter++;
    if( counter >= ajaxCalls ) {
            // When all ajax calls has been done
        // Do something like hide waiting images, or any else function call
        $('*').css('cursor', 'auto');
    }
};

var loadPersons = function() {
        // Show waiting image, or something else
    $('*').css('cursor', 'wait');

    var url = global.ctx + '/loadPersons';
    $.getJSON(url, function(data) {
            // Fun things
    })
    .complete(function() { **ajaxCallComplete();** });
};

var loadCountries = function() {
    // Do things
    var url = global.ctx + '/loadCountries';
    $.getJSON(url, function(data) {
            // Travels
    })
    .complete(function() { **ajaxCallComplete();** });
};

var loadCities = function() {
    // Do things
    var url = global.ctx + '/loadCities';
    $.getJSON(url, function(data) {
            // Travels
    })
    .complete(function() { **ajaxCallComplete();** });
};

$(document).ready(function(){
    loadPersons();
    loadCountries();
    loadCities();
});
看看我的解决方案:

1.将此函数(和变量)插入javascript文件:

var runFunctionQueue_callback;

function runFunctionQueue(f, index, callback) {

  var next_index = index + 1

  if (callback !== undefined) runFunctionQueue_callback = callback;

  if (f[next_index] !== undefined) {
    console.log(index + ' Next function avalaible -> ' + next_index);
    $.ajax({
      type: 'GET',
      url: f[index].file,
      data: (f[index].data),
      complete: function() {
        runFunctionQueue(f, next_index);
      }
    });
  } else {
    console.log(index + ' Last function');
    $.ajax({
      type: 'GET',
      url: f[index].file,
      data: (f[index].data),
      async: false,
      complete: runFunctionQueue_callback
    });
  }
}
2.使用您的请求构建一个数组,如下所示:

$.ajaxQueue({
        url: 'page.php',
        data: {id: 1},
        type: 'POST',
        success: function(data) {
            $('#status').html(data);
        }
    });
var f = [
           {file: 'file_path', data: {action: 'action', data: 'any_data}},
           {file: 'file_path', data: {action: 'action', data: 'any_data}},
           {file: 'file_path', data: {action: 'action', data: 'any_data}},
           {file: 'file_path', data: {action: 'action', data: 'any_data}}
        ];
$.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,            
        ...
    });
}
// Define how many Ajax calls must be done
var ajaxCalls = 3;
var counter = 0;
var ajaxCallComplete = function() {
    counter++;
    if( counter >= ajaxCalls ) {
            // When all ajax calls has been done
        // Do something like hide waiting images, or any else function call
        $('*').css('cursor', 'auto');
    }
};

var loadPersons = function() {
        // Show waiting image, or something else
    $('*').css('cursor', 'wait');

    var url = global.ctx + '/loadPersons';
    $.getJSON(url, function(data) {
            // Fun things
    })
    .complete(function() { **ajaxCallComplete();** });
};

var loadCountries = function() {
    // Do things
    var url = global.ctx + '/loadCountries';
    $.getJSON(url, function(data) {
            // Travels
    })
    .complete(function() { **ajaxCallComplete();** });
};

var loadCities = function() {
    // Do things
    var url = global.ctx + '/loadCities';
    $.getJSON(url, function(data) {
            // Travels
    })
    .complete(function() { **ajaxCallComplete();** });
};

$(document).ready(function(){
    loadPersons();
    loadCountries();
    loadCities();
});
3.创建回调函数:

function Function_callback() {
  alert('done');
}
4.使用以下参数调用runFunctionQueue函数:

runFunctionQueue(f, 0, QuestionInsert_callback);
// first parameter: array with requests data
// second parameter: start from first request
// third parameter: the callback function

使用
ajaxStop
事件

例如,假设您在获取100个ajax请求时有一条正在加载…消息,并且希望在加载后隐藏该消息

从jQuery:


请注意,它将等待在该页面上完成所有ajax请求。

基于@BBonifield answer,我编写了一个实用函数,以便信号量逻辑不会在所有ajax调用中传播

untilAjax
是一个实用函数,它在所有Ajax调用完成时调用回调函数

$(document).ajaxStop(function() {
     // This function will be triggered every time any ajax request is requested and completed
});
ajaxObjs
是一组ajax设置对象
[http://api.jquery.com/jQuery.ajax/]

fn
是回调函数

function untilAjax(ajaxObjs, fn) {
  if (!ajaxObjs || !fn) {
    return;
  }
  var ajaxCount = ajaxObjs.length,
    succ = null;

  for (var i = 0; i < ajaxObjs.length; i++) { //append logic to invoke callback function once all the ajax calls are completed, in success handler.
    succ = ajaxObjs[i]['success'];
    ajaxObjs[i]['success'] = function(data) { //modified success handler
      if (succ) {
        succ(data);
      }
      ajaxCount--;
      if (ajaxCount == 0) {
        fn(); //modify statement suitably if you want 'this' keyword to refer to another object
      }
    };
    $.ajax(ajaxObjs[i]); //make ajax call
    succ = null;
  };

我的解决办法如下

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);
          });
工作得很好。我尝试了很多不同的方法,但我发现这是最简单和最可重用的。希望它能有所帮助

jQuery现在为此定义了一个

它接受任意数量的延迟对象作为参数,并在所有延迟对象解析时执行函数

这意味着,如果您想启动(例如)四个ajax请求,然后在它们完成时执行一个操作,您可以执行如下操作:

$.ajaxQueue({
        url: 'page.php',
        data: {id: 1},
        type: 'POST',
        success: function(data) {
            $('#status').html(data);
        }
    });
var f = [
           {file: 'file_path', data: {action: 'action', data: 'any_data}},
           {file: 'file_path', data: {action: 'action', data: 'any_data}},
           {file: 'file_path', data: {action: 'action', data: 'any_data}},
           {file: 'file_path', data: {action: 'action', data: 'any_data}}
        ];
$.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,            
        ...
    });
}
// Define how many Ajax calls must be done
var ajaxCalls = 3;
var counter = 0;
var ajaxCallComplete = function() {
    counter++;
    if( counter >= ajaxCalls ) {
            // When all ajax calls has been done
        // Do something like hide waiting images, or any else function call
        $('*').css('cursor', 'auto');
    }
};

var loadPersons = function() {
        // Show waiting image, or something else
    $('*').css('cursor', 'wait');

    var url = global.ctx + '/loadPersons';
    $.getJSON(url, function(data) {
            // Fun things
    })
    .complete(function() { **ajaxCallComplete();** });
};

var loadCountries = function() {
    // Do things
    var url = global.ctx + '/loadCountries';
    $.getJSON(url, function(data) {
            // Travels
    })
    .complete(function() { **ajaxCallComplete();** });
};

var loadCities = function() {
    // Do things
    var url = global.ctx + '/loadCities';
    $.getJSON(url, function(data) {
            // Travels
    })
    .complete(function() { **ajaxCallComplete();** });
};

$(document).ready(function(){
    loadPersons();
    loadCountries();
    loadCities();
});
在我看来,它提供了一个干净清晰的语法,并避免了涉及任何全局变量,如ajaxStart和ajaxStop,这可能会在页面开发过程中产生不必要的副作用

如果您事先不知道需要等待多少ajax参数(即,您希望使用数量可变的参数),那么仍然可以这样做,但这只是有点棘手。看(也许)


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

一点解决方法如下:

$.ajaxQueue({
        url: 'page.php',
        data: {id: 1},
        type: 'POST',
        success: function(data) {
            $('#status').html(data);
        }
    });
var f = [
           {file: 'file_path', data: {action: 'action', data: 'any_data}},
           {file: 'file_path', data: {action: 'action', data: 'any_data}},
           {file: 'file_path', data: {action: 'action', data: 'any_data}},
           {file: 'file_path', data: {action: 'action', data: 'any_data}}
        ];
$.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,            
        ...
    });
}
// Define how many Ajax calls must be done
var ajaxCalls = 3;
var counter = 0;
var ajaxCallComplete = function() {
    counter++;
    if( counter >= ajaxCalls ) {
            // When all ajax calls has been done
        // Do something like hide waiting images, or any else function call
        $('*').css('cursor', 'auto');
    }
};

var loadPersons = function() {
        // Show waiting image, or something else
    $('*').css('cursor', 'wait');

    var url = global.ctx + '/loadPersons';
    $.getJSON(url, function(data) {
            // Fun things
    })
    .complete(function() { **ajaxCallComplete();** });
};

var loadCountries = function() {
    // Do things
    var url = global.ctx + '/loadCountries';
    $.getJSON(url, function(data) {
            // Travels
    })
    .complete(function() { **ajaxCallComplete();** });
};

var loadCities = function() {
    // Do things
    var url = global.ctx + '/loadCities';
    $.getJSON(url, function(data) {
            // Travels
    })
    .complete(function() { **ajaxCallComplete();** });
};

$(document).ready(function(){
    loadPersons();
    loadCountries();
    loadCities();
});

希望是有用的…

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

$(document).ajaxStop(function () {
  // 0 === $.active
});
在这种情况下,您既不需要猜测应用程序中发生了多少请求(这些请求可能在将来完成),也不需要深入研究函数的复杂逻辑,也不需要找出哪些函数正在执行
HTTP(S)
请求

这里还可以绑定到您需要的任何
HTML
节点 think可能会被requst修改


更新:
如果您想坚持使用
ES
语法,那么您可以使用已知的
ajax
方法:

Promise.all([ajax1(),ajax2())。然后(()=>{
//所有请求都已成功完成
}).catch(()=>{
//所有请求均已完成,但一个或多个请求失败
})
这里有趣的一点是,它同时适用于
承诺
$.ajax
请求

这是演示


更新2:
使用语法的最新版本:

试试看{
const results=wait Promise.all([ajax1(),ajax2()]))
//做其他动作
}捕获(ex){}

如果你需要简单的东西;一次性回拨

        //multiple ajax calls above
        var callback = function () {
            if ($.active !== 0) {
                setTimeout(callback, '500');
                return;
            }
            //whatever you need to do here
            //...
        };
        callback();

这样试试。在java脚本函数中进行循环,等待ajax调用完成

function getLabelById(id)
{
    var label = '';
    var done = false;
    $.ajax({
       cache: false,
       url: "YourMvcActionUrl",
       type: "GET",
       dataType: "json",
       async: false,
       error: function (result) {
         label='undefined';
         done = true;
        },
       success: function (result) {
            label = result.Message;
            done = true;
        }
     });

   //A loop to check done if ajax call is done.
   while (!done)
   {
      setTimeout(function(){ },500); // take a sleep.
   }

    return label;
}

我找到了一个简单的方法,使用
shift()

你也可以用

我认为它比$.when好,因为您可以合并各种不支持即时承诺(如超时、SqlLite调用等)的异步调用,而不仅仅是ajax请求。

如果您从头开始,我强烈建议使用

尽管这个问题有超过百万个答案,我还是很惊讶