停止代码直到AJAX调用在$ .each循环内完成

时间:2016-04-21 15:46:12

标签: javascript jquery html ajax asynchronous

我有一个函数可以使用jQuery通过$.each调用从外部文件加载HTML。

这些ajax调用在$('img').each(function(){ var cotainer_html = $('.cotainer_html').clone(); /* Get Image Content */ $.ajax({ url: '/assets/ajax/get_studio_image.php', type:'GET', success:function(data){ cotainer_html.find('.replaceme').replaceWith(data); } }); }); 循环内运行,我需要在循环继续之前完成这个ajax调用。这是我的代码:

async:false

我知道我可以设置composer update --no-scripts,但我听说这不是一个好主意。有任何想法吗?

2 个答案:

答案 0 :(得分:2)

要实现此目的,您可以将每个请求放入一个数组,并将apply()该数组放入$.when。试试这个:

var requests = [];
$('img').each(function(){
    var cotainer_html = $('.cotainer_html').clone();
    /* Get Image Content */
    requests.push($.ajax({
       url: '/assets/ajax/get_studio_image.php',
       type:'GET',
       success:function(data){
          cotainer_html.find('.replaceme').replaceWith(data);
       }
    }));
});

$.when.apply($, requests).done(function() {
    console.log('all requests complete');
});

请注意,您要在每个请求中替换相同的内容,因此唯一对UI有影响的是最后一个请求。前面的是多余的。

另请注意, 永远不要使用async: false 。它会锁定浏览器的UI线程,直到请求完成,这使得它看起来已经崩溃到用户。这是一种可怕的做法。使用回调。

  

OP似乎希望调用以串行方式运行,而不是并行运行

如果是这种情况,您可以使用递归:

function makeRequest($els, index) {
    var cotainer_html = $('.cotainer_html').clone();
    $.ajax({
       url: '/assets/ajax/get_studio_image.php',
       type:'GET',
       success:function(data){
          cotainer_html.find('.replaceme').replaceWith(data);
          if ($els.eq(index + 1).length) {
              makeRequest($els, ++index);
          } else {
              console.log('all requests complete');
          }
       }
    });
}

makeRequest($('img'), 0);

答案 1 :(得分:2)

您可以使用伪递归循环:

var imgs = $('img').get();

var done = (function loop() {
    var img = imgs.shift();
    if (img) {
        var cotainer_html = $('.cotainer_html').clone();
        /* Get Image Content */
        return $.get('/assets/ajax/get_studio_image.php')
         .then(function(data) {
            cotainer_html.find('.replaceme').replaceWith(data);
        }).then(loop);
   } else {
       return $.Deferred().resolve();  // resolved when the loop terminates
   }
})();

这将获取列表中的每个元素,获取所需的图像,然后.then()重新开始直到没有任何内容。

立即调用函数表达式本身返回Promise,因此您可以将.then()调用链接到循环完成后将调用的调用:

done.then(function() {
    // continue your execution here 
    ...
});