如何等待jQuery ajax请求在循环中完成?

时间:2013-11-29 18:09:16

标签: javascript 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');
    }
  });
}

它上传的图片非常好,但问题是我找不到逐个上传图片的方法,我试图将选项 async设置为false 但它冻结了网络浏览器直到所有图像上传都不是我想要的,我想以某种方式模拟这个“async:false”选项来执行相同的操作但不冻结Web浏览器。

怎么做?

5 个答案:

答案 0 :(得分:62)

您可以创建一系列承诺,以便一旦所有承诺得到解决,您就可以运行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

答案 1 :(得分:3)

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

你可以尝试类似的东西:

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

答案 2 :(得分:3)

对于支持原生Promise.all的jQuery 3.x +和现代浏览器,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) }) 而不是循环。

prefetch_related

答案 3 :(得分:2)

我会尝试jQuery.when,所以你仍然可以使用异步调用但是延迟,比如:

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之外完成,然后按照charlietfl的回答推荐到数组中。您可以使用(异步)ajax调用并将其推迟到$.when内,请参阅JSFIDDLE

答案 4 :(得分:0)

在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  */
});