如何等待,直到jQuery ajax请求完成循环?

我有这样的代码:

for (var i = 0; i < $total_files; i++) { $.ajax({ type: 'POST', url: 'uploading.php', context: $(this), dataType: 'json', cache: false, contentType: false, processData: false, data: data_string, success: function(datas) { //does something }, error: function(e) { alert('error, try again'); } }); } 

它上传图像很好,但问题是我找不到一个一个上传图像的方式,我试图把选项asynchronous为false,但它冻结了网页浏览器,直到所有的图像上传,这不是我希望,我想模仿某种方式这个“async:false”选项来执行相同的事情,但不冻结网页浏览器。

如何做到这一点?

您可以创build一个承诺数组,以便一旦所有的承诺解决,您可以运行您的all done代码。

 var promises = []; for (var i = 0; i < $total_files; i++){ /* $.ajax returns a promise*/ var request = $.ajax({ /* your ajax config*/ }) promises.push( request); } $.when.apply(null, promises).done(function(){ alert('All done') }) 

DEMO

在每次调用时填充一个数组,并在前一次完成时调用下一个项目。

你可以尝试这样的事情:

  window.syncUpload = { queue : [], upload : function(imagesCount) { var $total_files = imagesCount, data_string = ""; /* Populates queue array with all ajax calls you are going to need */ for (var i=0; i < $total_files; i++) { this.queue.push({ type: 'POST', url: 'uploading.php', context: $(this), dataType: 'json', cache: false, contentType: false, processData: false, data: data_string, success: function(datas) { //does something }, error: function(e){ alert('error, try again'); }, /* When the ajax finished it'll fire the complete event, so we call the next image to be uploaded. */ complete : function() { this[0].uploadNext(); } }); } this.uploadNext(); }, uploadNext : function() { var queue = this.queue; /* If there's something left in the array, send it */ if (queue.length > 0) { /* Create ajax call and remove item from array */ $.ajax(queue.shift(0)); } } } 

只需使用syncUpload.upload(NUMBER_OF_IMAGES);

我会尝试jQuery.when所以你仍然可以使用asynchronous调用,但推迟,如下所示:

 jQuery(document).ready(function ($) { $.when( //for (var i = 0; i < $total_files; i++) { $.ajax({ // ajax code }) //} ).done(function () { // perform after ajax loop is done }); }); // ready 

编辑 :ajax迭代应该在$.when .when之外完成, 并按charlietfl的答案推荐到数组中。 您可以使用(asynchronous)ajax调用并在$.when .when内部推迟它,请参阅JSFIDDLE

对于支持原生Promise jQuery 3.x +和现代浏览器, Promise.all可以这样使用:

 var promises = []; for (var i = 0; i < $total_files; i++) { // jQuery returns a prom promises.push($.ajax({ /* your ajax config*/ })) } Promise.all(promises) .then(responseList => { console.dir(responseList) }) 

如果你的文件已经存储在列表中,那么你可以使用map而不是循环。

 var fileList = [/*... list of files ...*/]; Promise.all(fileList.map(file => $.ajax({ /* your ajax config*/ }))) .then(responseList => { console.dir(responseList) }) 

在jQuery中的一个声明

 $.when.apply(null, $.map(/*input Array|jQuery*/, function (n, i) { return $.get(/* URL */, function (data) { /* Do something */ }); })).done(function () { /* Called after all ajax is done */ }); 

你应该反转你的代码依赖。 由于AJAX是asynchronous调用,因此循环将不会等待先前的调用完成。

只有当您的上一个AJAX通过成功function完成并且统计上传的文件总数时,您才应该发送另一个AJAX。

像这样:

  $total_files = 5; $total_files_uploaded = 0; // Pass parameter to function if needed or get it from higher scope function uploadFile() { if ( $total_files_uploaded == $total_files ) return; $.ajax({ type: 'POST', url: 'uploading.php', context: $(this), dataType: 'json', cache: false, contentType: false, processData: false, data: data_string, success: function(datas) { // if finished, do another round of upload $total_files_uploaded++; uploadFile(); }, error: function(e){ alert('error, try again'); } }); } 

我不确定你在$(this)中传递的是什么,但是确保每次函数调用都传递给它。