【问题标题】:Progress on jQuery 3 $.when with multiple deferredsjQuery 3 $.when 的进展与多个延迟
【发布时间】:2017-05-19 13:06:29
【问题描述】:

在 jQuery 3(参见 issue)中,progress 上的 $.when 改变了行为。我希望在我的每个延期都得到解决时收到进度通知:

var urls = [
  'https://httpbin.org/delay/2',
  'https://httpbin.org/delay/1'
];
console.log('started');
var deferreds = $.map(urls, function(url) {
  var d = $.Deferred();
  $.ajax({
    url: url,
    type: 'GET'
  })
  .always(function(){
    console.log('done %o', url)
    d.notify();
    d.resolve.apply(this, arguments);
  });
  return d.promise();
});

$.when.apply(jQuery, deferreds).progress(function(){
  // Does not call
  console.log('progress?');
}).done(function(){
  console.log('all done');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>

代码也在codepen。当前输出:

“开始”
“完成https://httpbin.org/delay/1
“完成https://httpbin.org/delay/2
“全部完成”

我希望在每个完成的请求后看到progress? 输出。

当前的 jQuery API 有没有很好的方法来实现这种行为?

【问题讨论】:

    标签: jquery jquery-deferred jquery-3


    【解决方案1】:

    允许组件承诺通知聚合承诺:

    • 不完全理性,
    • 很可能是 jQuery 1 和 2 中很少使用的功能,因为它从未正常工作过。

    考虑:

    var urls = [
        'https://httpbin.org/delay/2',
        'https://httpbin.org/delay/1'
    ];
    console.clear();
    console.log('started');
    var promises = urls.map(function(url, i) {
        return $.Deferred(function(d) {
            $.ajax({
                url: url,
                type: 'GET'
            })
            .always(function() {
                console.log('done', i, url);
                d.notify(i);
                d.resolve.apply(this, arguments);
            });
        }).promise();
    });
    
    $.when.apply(null, promises).progress(function(x) {
        console.log('progress ' + x);
    }).done(function() {
        console.log('all done');
    });
    

    在 jQuery 1 或 2 中,您可以合理地期望:

    “开始”
    “完成 1 https://httpbin.org/delay/1
    “进度 1”
    “完成 0 https://httpbin.org/delay/2
    “进度 0”
    “全部完成”

    但我明白了:

    “开始”
    “完成 1 https://httpbin.org/delay/1
    “进度未定义”
    “完成 0 https://httpbin.org/delay/2
    “进度 0”
    “全部完成”

    天知道undefined来自哪里。

    现在尝试交换两个网址的顺序 - 我明白了:

    “开始”
    “完成 0 https://httpbin.org/delay/1
    “进度 0”
    “完成 1 https://httpbin.org/delay/2
    “进度 0”
    “全部完成”

    仍然不如预期 - 现在你得到两次“进度 0”!

    恕我直言,这个功能在 jQuery 3 中被删除并不奇怪。

    【讨论】:

    • 有意思,以前不知道它坏了。您是否知道在解决/通知每个组件承诺时获取函数调用的方法?我对这个论点不太感兴趣(0 或 undefined 很好!)并且更希望有一种好方法来跟踪我所有并发请求的进度。
    • 我想知道你是否真的想要notify()/progress(),这与中间事件有关,而承诺仍处于未决状态。如果您想观察单个 ajax 调用的成功/失败,那么您已经在 .always() 处理程序中使用 console.log() 这样做了。当然,你可以做的不仅仅是console.log(),例如给用户一个进度条或消息来指示有多少个单独的ajax调用已经完成/失败,但这与.notify()/.progress()无关。
    • 我希望有一个很好的方法来分离 ajax 调用和进度处理,但我最终将进度逻辑放入 .always() - 无论如何谢谢!
    【解决方案2】:

    你可以试试下面的代码吗:

    var urls = [
      'https://httpbin.org/delay/2',
      'https://httpbin.org/delay/1'
    ];
    
    console.log('started');
    var deferreds = $.map(urls, function(url) {
      var d = $.Deferred();
      $.ajax({
        url: url,
        type: 'GET',
        success: function(){
          d.notify(); //notify the progress handler about the current progress
        } 
      })
      .always(function(){
        console.log('done %o', url)
        d.resolve.apply(this, arguments);
      });
      return d.promise();
    });
    
    $.when.apply(jQuery, deferreds).progress(function(){
      // Does not call
      console.log('progress?');
    }).done(function(){
      console.log('all done');
    });
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
    <div>
    </div>

    在这里,我们为ajax 添加了success 处理程序,我们通过它调用deferred.notify(),通过它调用progress

    【讨论】:

    • .success 不是一个有效的函数,但如果我使用.done 或将它放入.always(在d.resolve 上方),那么我仍然会得到相同的结果,.progress没有被调用
    • 哦...对不起。 success 必须是传递给 ajax 设置的选项的一部分。你是对的。
    • 别担心!恐怕结果相同 - 调用d.notify 没有帮助(无论是来自success 回调还是来自延迟的.always)。我认为这与 3.0 中 jQuery 的变化有关 - 请参阅我上面链接的问题。
    • 我使用 .always 是因为我希望在所有请求完成(成功或失败)后调用 $.when .done 函数。
    • 恐怕我正在使用 jQuery 3(见标签),切换到 1 不是一个选项
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-21
    • 2014-03-01
    • 2012-08-18
    • 1970-01-01
    • 1970-01-01
    • 2013-03-09
    相关资源
    最近更新 更多