【问题标题】:Deferred and Ajax延迟和 Ajax
【发布时间】:2016-08-31 01:05:36
【问题描述】:

像这样读取 JSON 服务:

$.ajax({
  url:'activeIDs',
  success : function(data){ // data = [14,15]
    var tableRows = [];
    for (var dataIndex=0; dataIndex < data.length; dataIndex++) {
      var isLast = dataIndex == (data.length - 1);
      $.ajax({
        url: 'info?id=' + data[dataIndex],
        success: function(data2) { // "foo", "bar"
          tableRows.push(data2.name);
          if (isLast) {
            alert(tableRows.length);
          }
        }
      });
    }
  }
});

第一个网络跟踪是:

  1. activeIDs = [14,15]
  2. info?id=14(需要 2 秒)="foo"
  3. info?id=15(需要 4 秒)="bar"

在这种情况下,警报给出“2”。

Seconds network-trace 不同:

  1. activeIDs = [14,15];
  2. info?id=14(需要 20 秒)="foo"(现在需要很长时间)
  3. info?id=15(需要 1 秒)="bar"

在这种情况下,警报会在一秒钟后提供1,这是不好!!!

问题:

如何使用 $.Deferred 代替 isLast

【问题讨论】:

  • 我猜你不能保证最后一个请求会最后完成。
  • 没错,只有$.Deferred 可能知道最后一个请求何时完成AFAIK。但是$.Deferred怎么用呢?
  • 我可以使用if (data.length == entries.length) {,但我真的很喜欢使用$.Deferred 的解决方案。
  • 为什么需要多个ajax调用?
  • 我已经根据 jQuery when 编辑了我的答案,因为 localStorage 是不可能的。 @PeterRader

标签: jquery ajax jquery-deferred


【解决方案1】:

您需要在alerting 之前等待所有请求完成。

$.ajax({
  url:'activeIDs',
  success : function(data){ // data = [14,15]
    var tableRows = [];
    var requests = [];
    for (var dataIndex=0; dataIndex < data.length; dataIndex++) {
      var isLast = dataIndex == data.length;

      var request = $.ajax({
        url: 'info?id=' + data[dataIndex]
      }).done(function(data2) { // "foo", "bar"
        tableRows.push(data2.name);
      });

      requests.push(request);
    }

    // wait for all requests to finish here
    $.when(requests).then(function(){
      // all success functions have been called and updated things appropriately
      alert(tableRows.length);
    }
  }
});

这假设所有请求都成功。 好像也有一些错别字

  • tableRows 在哪里更新?
  • entries 在哪里定义?

编辑 现在使用承诺风格的成功处理程序。应该在调用$.when().then 回调之前将结果推送到tableRows

【讨论】:

  • 这很酷,$.when 返回一个 Promise 并接受 Defferreds 作为参数,所以我认为这正是 OP 想要的。
  • 我需要requests-Array吗?
  • 是的,你需要将所有的 Deferreds 传递给$.when()
  • 原来是不正确的,then 在加入成功处理程序之前触发。如何重现:在tableRows.push(data2.name); 之前插入alert('wait');。你会变成三个警报:“wait”、“wait”和“0
  • 啊,应该使用来自$.ajax 的promise 样式而不是成功回调以允许可预测的行为......答案已更新。尽量不要使用 successerror 回调。最好使用 Deferred/Promise 样式
【解决方案2】:

为什么要 $.Deferred ?您的 $.ajax 调用正在返回一个承诺,因此,您可以使用它:

var promisesArray = [];
for (var dataIndex=0; dataIndex < data.length; dataIndex++) {
  promisesArray.push($.ajax({...}));
}
 $.when.apply($, promisesArray).then(...);

(灵感来自this 答案)

如果需要,您可以通过采用此解决方案并将其传递给 deferred 来使用 deferred,但这不是必需的:

var x = $.Deferred(function(defer){  
    var promisesArray = [];
    for (var dataIndex=0; dataIndex < data.length; dataIndex++) {
      promisesArray.push($.ajax({...}));
    }
     $.when.apply($, promisesArray).done(function(data) { defer.resolve(data); });
});
return x.promise();

(未测试,对不起)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-12-25
    • 2021-12-02
    • 2011-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多