首页 > 解决方案 > Ajax jQuery.when() 与 each() 循环

问题描述

有一个动态数量的元素具有 data-url 属性,其中包含用于返回其 HTML 内容的 ajax 调用的 URL。

<div class="element" data-url="data1.php"></div>
<div class="element" data-url="data2.php"></div>
<div class="element" data-url="data3.php"></div>
...

我需要通过 AJAX 加载他们的内容,并在完成后对其进行处理。

我不认为我可以使用 .ajaxStop() 因为在这些调用之后有更多不同的 ajax 调用,我不能等到它们全部完成。

所以我尝试使用 jQuery.when() 和 .each() 循环来遍历所有元素并加载它们的内容,但是 .done() 函数会在循环中的所有 ajax 调用完成之前触发。

$.when(
    $('.element').each(function() {
        var el = $(this);
        $.get($(el).data('url'), function(data) {
            $(el).html(data);
        });
    })
).done(function() {
    // do something after all calls are finished
});

标签: javascriptjqueryajax

解决方案


您的逻辑的问题是each()返回一个 jQuery 对象。由于这不是$.when()立即解决的承诺,done()而是在您的所有/任何$.get请求完成之前调用。

要解决此问题,请从调用中创建一组承诺$.get()并将其应用于$.when(). 尝试这个:

var promises = $('.element').map(function() {
  var $el = $(this);
  return $.get($el.data('url'), function(data) {
    $el.html(data);
  });
}).get()

$.when.apply($, promises).done(function() {
  // do something after all calls are finished
});

另请注意,虽然这会起作用,但可能会在循环中用请求淹没您的服务器并不是一个可扩展的解决方案。更好的模式是将元素中的所有data-url属性聚合.element到单个请求中,然后在此请求完成后手动更新 DOM。


推荐阅读