【问题标题】:How to wait until jQuery ajax request finishes in a loop?如何等到 jQuery ajax 请求循环完成?
【发布时间】:2013-11-29 18:09:15
【问题描述】:

我有那个代码:

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" 选项来执行相同的操作,但不会冻结网络浏览器。

如何做到这一点?

【问题讨论】:

  • 总体目标是什么?
  • 它是在上传到服务器后立即显示每张上传的图像,并排显示,我正在尝试发布的所有解决方案,并会看看哪一个适合我的需求。
  • 承诺是要走的路,建议一次上传一个的解决方案将花费比必要更长的时间
  • 好吧,我测试了你所有的解决方案,但没有一个能按我想要的方式工作:(
  • 您从未概述过您想要的行为。你只是说你想要类似于 asynch false,但没有说为什么

标签: javascript jquery ajax


【解决方案1】:

您可以创建一组承诺,以便在解决所有承诺后,您可以运行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

【讨论】:

  • 您的done 语法正确吗? ...好的,我没有看到您的编辑,但现在
  • 我看了你的demo,虽然最后叫'All done',但是执行的顺序搞错了。有什么办法可以改正吗?
  • @failed.down 如果找不到答案,最好提出一个新问题
  • 没关系,我找到了,我只是使用 ajax 而不是 get 并将 jsonp 替换为 json 并在 ajax 选项中使用 async:false
  • 这很有帮助,但如果任何 ajax 调用失败,.done 函数将不会执行
【解决方案2】:

对于支持原生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)
})

【讨论】:

  • 谢谢!为了让我的生活更轻松。
【解决方案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);

【讨论】:

  • 你试过这个代码吗?它将按照您创建队列数组的顺序加载图像。
【解决方案4】:

我会尝试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

EDIT :ajax 迭代应该在$.when 之外完成,并按照charlietfl 的回答推入一个数组中。您可以使用(异步)ajax 调用并将其推迟到 $.when 中,请参阅 JSFIDDLE

【讨论】:

  • 您忘记在for 循环周围放置一个函数。 $.when 不是期待一个承诺或一系列承诺吗?
  • 我得到“SyntaxError: missing : after property id for (var i=0; i
  • 我只是写得很快,但我想你应该去找charlietfl的答案(我会删除这个)
  • @t.niese :顺便说一句,您可以在 $.when 内使用 ajax 调用,而无需 array ... 这是 charlietfl 调整后的 jsfiddle ... 当然,适用于单个 ajax 调用
  • 实际上,我不会删除我的答案,因为讨论可能对未来的访问者有用;)
【解决方案5】:

在一个带有 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  */
});

【讨论】:

    猜你喜欢
    • 2020-03-17
    • 2014-07-25
    • 1970-01-01
    • 2011-07-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多