如何等待,直到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)中传递的是什么,但是确保每次函数调用都传递给它。