javascript - Deferred 和/或 Promise 数组的 jQuery.when() 进度

标签 javascript jquery promise jquery-deferred

我正在使用 jQuery 的 .when()wrap an array of promises以便在所有 promise 都已解决时我可以采取一些行动。

$.when.apply($, requests).done(function () {
    console.log(arguments); //it is an array like object which can be looped
    var total = 0;
    $.each(arguments, function (i, data) {
        console.log(data); //data is the value returned by each of the ajax requests

        total += data[0]; //if the result of the ajax request is a int value then
    });

    console.log(total)
});

假设我想在每个单独的 promise 得到解决时收到通知,作为显示进度的一种方式。例如,如果 requests 有 50 个请求,其中 3 个已解决,我希望能够在 6% 处显示进度条。有没有办法使用 $.when 以便它可以在不修改内部 promise 及其进度事件的情况下返回总体进度?

最佳答案

$.when() 不会为您发送进度通知。在每个单独的 promise 上注册进度通知,或者您可以制作自己的 $.when() 版本,首先在每个 promise 上注册完成通知,然后调用 $.when( )

$.whenWithProgress = function(arrayOfPromises, progessCallback) {
   var cntr = 0;
   for (var i = 0; i < arrayOfPromises.length; i++) {
       arrayOfPromises[i].done(function() {
           progressCallback(++cntr, arrayOfPromises.length);
       });
   }
   return jQuery.when.apply(jQuery, arrayOfPromises);
}

$.whenWithProgress(requests, function(cnt, total) {
    console.log("promise " + cnt + " of " + total + " finished");
}).then(function() {
    // done handler here
}, function() {
    // err handler here
});

我一直在考虑这个问题,让我有点困扰的是你想要进度通知,jQuery promise 有一个进度机制,但我们没有使用它。这意味着进度通知不像它们应有的那样具有可扩展性。

不幸的是,因为 $.when() 返回一个 promise(不是延迟的)并且你不能在 promise 上使用 .notify() 来触发进度通知,上面的代码是最简单的方法。但是,为了使用 .progress 通知而不是自定义回调,可以这样做:

$.whenWithProgress = function(arrayOfPromises) {
   var cntr = 0, defer = $.Deferred();
   for (var i = 0; i < arrayOfPromises.length; i++) {
       arrayOfPromises[i].done(function() {
           defer.notify(++cntr, arrayOfPromises.length);
       });
   }
   // It is kind of an anti-pattern to use our own deferred and 
   // then just resolve it when the promise is resolved
   // But, we can only call .notify() on a defer so if we want to use that, 
   // we are forced to make our own deferred
   jQuery.when.apply(jQuery, arrayOfPromises).done(function() {
       defer.resolveWith(null, arguments);
   });
   return defer.promise();
}

$.whenWithProgress(requests).then(function() {
    // done handler here
}, function() {
    // err handler here
}, function(cnt, total) {
    // progress handler here
    console.log("promise " + cnt + " of " + total + " finished");
});

反对第二个实现的一个论点是, promise 标准的努力似乎正在远离以任何方式将进展与 promise 联系起来(进展将有一个单独的机制)。但是,它现在在 jQuery 中,并且可能会在很长一段时间内存在(jQuery 不严格遵守 promise 标准),所以选择哪种方式真的是您的选择。

关于javascript - Deferred 和/或 Promise 数组的 jQuery.when() 进度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26066198/

相关文章:

javascript - $(#cart-continue).click(function) 未被调用

javascript - 为什么 Promise-Limit 在 Nodejs 中不起作用?

javascript - 在 .then() 中显式调用 resolve()

javascript - 如何将 Promises 与 if 结合起来?

javascript - 从 JS 对象到 JSON Angular

javascript - 使用 jQuery 从单个 HTML 列表进行实时搜索和排序

javascript - 如何使用 jQuery 适配器将配置信息传递到 CKEditor?

javascript - jQuery 通过 ID 查找元素,如果存在则删除它

Javascript 在字符串中引用?

events - 确定用户是否单击滚动条或内容(onclick 对于 native 滚动条)