【问题标题】:How to transform an array of promise objects into a promise object of an array?如何将 promise 对象数组转换为数组的 promise 对象?
【发布时间】:2013-04-19 06:25:02
【问题描述】:

有没有办法将 promise 对象数组转换为数组的 promise 对象?我正在寻找在 AngularJS 中行为类似于 $q.all(promises) 的东西。

这是我的代码:

var getPages = function(courses) {
  var courses_promises = courses.filter(function(item) {
    return item.courses[0].home_link;
  }).map(function(item) {
    deferred = $.Deferred();
    item["class_link"] = item.courses[0].home_link;
    item["home_link"] = item["class_link"] + "class/index";
    $.get(item.home_link)
       .then(function(response) {
        item["html"] = response;
        deferred.resolve(item);
       });
    return deferred.promise();
  });
  return $.when.apply($, courses_promises);
};  

我希望getPages 函数返回一个单一的promise,该promise 将用一个值数组解析,每个值对应于promise 数组中相同索引处的promise。如果任何一个 Promise 以一个拒绝的方式解决,这个产生的 Promise 将以同样的拒绝方式解决。

然后我会使用

getPages.then(getEvents)

其中getEvents 是另一个函数,它需要一个数组,其中的元素由getPages 解析。

谁能帮帮我?谢谢!

【问题讨论】:

    标签: jquery promise q


    【解决方案1】:

    对于那些不想引入另一个库的人(尽管我可以确认 Q 很棒,它似乎是 node 的最佳承诺系统),这里是使用 jQuery 的 whenQ.all 的实现:

    function all(arrayOfPromises) {
        return jQuery.when.apply(jQuery, arrayOfPromises).then(function() {
            return Array.prototype.slice.call(arguments, 0);
        });
    };
    

    这要解决两个问题:

    1. jQuery.when 接受可变数量的参数,而不是接受一个数组,因此我们必须使用 apply 调用它,以提供我们的承诺数组。
    2. 组合的 Promise 使用多个参数解决,而不是单个数组参数,因此我们必须将 arguments 转换为真正的数组(使用 slice)。

    因此:

    var getAnimal = function(animal) {
        return $.get('animals/' + animal);
    };
    
    var arrayOfPromisesToAnimals = ['frog', 'cat', 'horse'].map(getAnimal);
    
    var promiseToArrayOfAnimals = all(arrayOfPromisesToAnimals);
    
    promiseToArrayOfAnimals.then(function(arrayOfAnimals) {
    
        arrayOfAnimals.forEach(function(animal) {
            console.log(animal);
        });
    });
    

    【讨论】:

      【解决方案2】:

      promises 是一个数组,Q.all(promises) 的 jQuery 等效项是:

      jQuery.when.apply(null, promises);
      

      许多 jQuery 程序员使用的同时同意这是笨拙的。 jQuery.when() 最好接受一个数组。

      编辑

      现在我已经看到了完整的 getPages 函数,我可以更好地建议一个 jQuery 解决方案:

      我觉得就这么简单:

      var getPages = function(courses) {
          var promises = courses.map(function(c) {
              if(!c.courses[0].home_link) return null;//filter action
              return $.get(c.courses[0].home_link + "class/index").done(function(response) {
                  c.html = response;
              });
          }).get();//Remove jQuery wrapper to reveal an array of jqXHR promises.
          return $.when.apply($, promises);
      };
      

      $.when.apply($, promises) 行总是正确的。您只需要确保promises 是真正的javascript Array,而不是jQuery 集合。

      【讨论】:

      • 谢谢,但这对我不起作用。我有一个承诺数组,每个承诺都用一个值解决,该值将传递给 then 方法。当我尝试 $.when.apply($, promises).then(function(promises){console.log(promises)}) 时,它会在控制台上打印出第一个 promise 的值。我希望结果是一个 promise 数组,并且该数组中的每个元素都是每个 promise 解析的值。
      • 这就是为什么 jQuery 很讨厌这种事情,如果你这样做 console.log(arguments) 你会得到你想要的,因为 jQuery 将结果分散在你传递给的函数的参数中.
      • jQuery.when.apply(null, promises)$.when.apply($, promises) 的行为应该相同。 $ === jQuery,在这种情况下传递给apply()的第一个参数是任意的。
      • 但实际上我想返回一个完整的数组,而不仅仅是一个承诺。
      • 是的,最后我用Q解决了这个问题。谢谢你,你太棒了!
      【解决方案3】:

      如果您使用的是Q,那么就这样做:

      Q.all(promises)
      

      这通常比使用 jQuery 来实现你的承诺要好得多,因为 Q 的设计要好得多。此外,给Q.all jQuery 承诺是安全的,它会很好地吸收它们。

      如果你不想使用 Q,我相信 $.when 会做类似的事情,但它没有那么干净和简单。

      【讨论】:

      • 谢谢。但是如何在我的 js 文件中使用 q?
      • 最简单的选择是从raw.github.com/kriskowal/q/master/q.min.js下载q,然后通过脚本标签(<script src="q.min.js"></script>)添加对它的引用
      • 如果您正在构建任何非常复杂的东西,我建议您使用 browserify.org 进行所有开发,然后它就像服务器端 node.js 一样工作,您可以这样做:npm install q安装和var Q = require('q') 使用
      • 谢谢。但我只是在写一个简单的脚本,我想用 jquery 来解决这个问题。而且我是网络开发的新手,感谢您向我介绍了图书馆的力量。谢谢!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-20
      • 1970-01-01
      • 2021-05-03
      • 2018-12-04
      • 2021-06-16
      • 1970-01-01
      相关资源
      最近更新 更多