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

时间:2022-08-23 18:14:10

I have that code :

我有那个密码:

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

It uploads images very well but the problem is that I can't find a way to upload the images one by one, I tried to put the option async to false but it freezes the web browser until all images are uploaded which is not what I want, I want to emulate somehow this "async : false" option to perform the same thing but without freezing the web browser.

它上传图片很好,但问题是,我不能找到一个方法来上传图片,我试图把选择异步虚假但它冻结web浏览器,直到所有的图片都上传这不是我想要的,我想效仿这“异步:假”选项来执行同样的事情但是没有冻结web浏览器。

How to do this ?

怎么做呢?

5 个解决方案

#1


54  

You can create an array of promises so that once all promises are resolved you can run your all done code.

您可以创建一个承诺数组,以便在解决所有承诺之后,可以运行所有已完成的代码。

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

演示

#2


3  

Populate an array with each call and call the next item when the previous is done.

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

You could try something like that:

你可以试试这样的方法:

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


        }

    }

Just call it using syncUpload.upload(NUMBER_OF_IMAGES);

只需使用syncUpload.upload(NUMBER_OF_IMAGES)调用它;

#3


3  

For jQuery 3.x+ and modern browser that support native Promise, Promise.all could be used this way:

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

If your files are already stored in a list then you could use map instead of a loop.

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

var fileList = [/*... list of files ...*/];

Promise.all(fileList.map(file => $.ajax({
      /* your ajax config*/
})))
.then(responseList => {
   console.dir(responseList)
})

#4


2  

I would try jQuery.when so you can still use asynchronous call but deferred, something like :

我将尝试jQuery。如果是这样,您仍然可以使用异步调用,但是延迟调用,比如:

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

EDIT : ajax iteration should be done outside $.when and pushed into an array as proposed by charlietfl's answer. You may use an (asynchronous) ajax call and defer it inside $.when though, see JSFIDDLE

编辑:ajax迭代应该在$之外完成。当,按charlietfl的建议推入数组。您可以使用(异步)ajax调用并将其延迟到$中。不过,当看到JSFIDDLE

#5


0  

In one statement with jquery

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

#1


54  

You can create an array of promises so that once all promises are resolved you can run your all done code.

您可以创建一个承诺数组,以便在解决所有承诺之后,可以运行所有已完成的代码。

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

演示

#2


3  

Populate an array with each call and call the next item when the previous is done.

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

You could try something like that:

你可以试试这样的方法:

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


        }

    }

Just call it using syncUpload.upload(NUMBER_OF_IMAGES);

只需使用syncUpload.upload(NUMBER_OF_IMAGES)调用它;

#3


3  

For jQuery 3.x+ and modern browser that support native Promise, Promise.all could be used this way:

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

If your files are already stored in a list then you could use map instead of a loop.

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

var fileList = [/*... list of files ...*/];

Promise.all(fileList.map(file => $.ajax({
      /* your ajax config*/
})))
.then(responseList => {
   console.dir(responseList)
})

#4


2  

I would try jQuery.when so you can still use asynchronous call but deferred, something like :

我将尝试jQuery。如果是这样,您仍然可以使用异步调用,但是延迟调用,比如:

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

EDIT : ajax iteration should be done outside $.when and pushed into an array as proposed by charlietfl's answer. You may use an (asynchronous) ajax call and defer it inside $.when though, see JSFIDDLE

编辑:ajax迭代应该在$之外完成。当,按charlietfl的建议推入数组。您可以使用(异步)ajax调用并将其延迟到$中。不过,当看到JSFIDDLE

#5


0  

In one statement with jquery

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