【问题标题】:Jquery Each Loop one after another when Defered Ajax Requests finishes当延迟的Ajax请求完成时,Jquery每个循环一个接一个
【发布时间】:2016-09-11 04:24:15
【问题描述】:

我无法解决这个问题,我发现了许多类似的例子,但似乎没有什么真正有效或适用于我的情况。

我的代码如下

$.each(versions, function(key,value) {
    progressText.html("Downloading Version " + value);
    ajaxUpdate('download',value).then(console.log(value));
});

function ajaxUpdate(step,value) {
    return $.ajax({
        url: 'action/' + step + '.update/',
        data: 'version=' + value
    })
}

基本上我的问题是它同时执行each,我希望它每个完成一个,然后继续下一个。

我该怎么做?

【问题讨论】:

  • 你试过了吗:ajaxUpdate('download',value).done(console.log(value));
  • 是的,我打算链接更多的 ajax 请求,这就是我使用 then() 的原因,但无论如何我都会得到相同的结果
  • @ChrisJamesChampeau - t1m0n 的回答有帮助吗?如果没有,我有其他可能可行的解决方案。
  • @Gavin 目前没有,但仍在尝试确定是否可行
  • @ChrisJamesChampeau 我在示例中有错误,现在应该没问题,尝试更新答案。还添加了超时示例

标签: jquery ajax


【解决方案1】:

您可以使用jQuery.Deferred() 对象一一发出ajax 请求。如果要在所有请求完成后调用某个函数,请在 each 循环之后使用 deffer.then(...)

function ajaxUpdate(step,value) {
    return $.ajax({
        url: 'action/' + step + '.update/',
        data: 'version=' + value
    })
}

// Emulate resolved deferred to be able to chain to it in each loop
var defer = $.Deferred().resolve();

$.each(versions, function(key, value) {
  // Add next deferred to chain, it will be invoked when previous is completed
  defer = defer.then(function(){
    return ajaxUpdate('download', value)
  });
});

defer.then(function(){
    console.log('All requests completed')
})

超时示例

var $log = $('#log');

function ajaxUpdate(url, step) {
  return $.Deferred(function() {

    setTimeout(function() {
      $log.append('<p>finished:' + step + '</p>')
      this.resolve();
    }.bind(this), Math.random() * 1000)

  })
}

var defer = $.Deferred().resolve();
var versions = [1, 2, 3, 4, 5];

$.each(versions, function(key, value) {
  defer = defer.then(function() {
    return ajaxUpdate('download', value)
  });
});

defer.then(function() {
  $log.append('<p>All Done</p>')
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="log"></div>

【讨论】:

  • 是的,好的,尝试了几次,但它有效
【解决方案2】:

我在这里发布了一个类似的问题,JQuery - Looping a .load() inside a 'for' statement 和对我有用的解决方案,我认为对你有用,因为如果我没看错,你希望它一次只做一个,是使用递归函数。

它现在不起作用的原因是因为 Ajax 执行异步请求,因此您的代码会一次执行,因为您的浏览器不必等待请求完成即可继续下一个请求.你要做的就是强迫它等待它完成,然后再继续下一个任务。如前所述,您可以使用递归函数来执行此操作。基本上,您创建一个仅在您的请求最终完成时才调用自身的函数。

当然,我使用了一个简单的 For 语句,而不是 .each 循环。浏览了一会儿后,我发现有人想在 .each 循环上使用递归函数的示例:jQuery recursive iteration over objects

所以你的代码应该是这样的:

 $.each(versions, function(key,value) { recursiveFunction(key, val) });

function recursiveFunction(key, val) {
    progressText.html("Downloading Version " + value);
    function ajaxUpdate(key,val) {
    $.ajax({
      url: 'action/' + step + '.update/',
      data: 'version=' + value
      }).done(function(data) {
            console.log(value);
            recursiveFunction(key, val);
        });
      }

}

代码可能需要稍微清理一下,因为我一生都无法习惯堆栈溢出代码编辑器,而且我可能需要更多代码来了解您正在尝试的内容做和如何做,但本质上应该是这样的。它应该可以工作,如果你稍微调整一下 c: 另请阅读我在此处包含的链接,它们应该可以帮助您理解我在这里想要传达的内容。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-02-13
    • 1970-01-01
    • 2016-06-26
    • 2016-04-13
    • 1970-01-01
    • 2019-03-24
    • 1970-01-01
    • 2019-08-06
    相关资源
    最近更新 更多