【问题标题】:Can I use $q.all in AngularJS with a function that does not return a .promise?我可以在 AngularJS 中将 $q.all 与不返回 .promise 的函数一起使用吗?
【发布时间】:2014-02-14 08:14:11
【问题描述】:

如果我有以下功能:

   doTask1: function ($scope) {
       var defer = $q.defer();
       $http.get('/abc')
           .success(function (data) {
               defer.resolve();
           })
           .error(function () {
               defer.reject();
           });
       return defer.promise;
   },

   doTask2: function ($scope) {
       var defer = $q.defer(); 
       var x = 99;
       return defer.promise;
   },

有人告诉我,我可以像这样等待两个承诺:

    $q.all([
            doTask1($scope),
            doTask2($scope)
    ])
        .then(function (results) {

        });

如果任务 2 没有返回承诺怎么办?我在 $q 文档中看到 对于 AngularJS,有一个“何时”。但是我不清楚如何使用它 而且没有例子。

是不是我必须让 doTask2 通过两行返回一个承诺:

var defer = q.defer()
return defer.promise

或者有没有更简单的方法来做到这一点?ll

【问题讨论】:

  • 如果 doTask2 不返回承诺,为什么需要 $q.all。如果你想等到所有包含的承诺都得到解决,你只需要 $q all 。如果您只想运行同步函数,请在 $q.all 承诺解决后执行。
  • @Geoff - 我以这个为例。我有很多功能,doTask2 或类似的东西只是其中之一。将所有这些函数放在 $q.all 中会使它看起来很清晰,并且很明显它们都需要完成,即使其中一个函数(例如 doTask2 会立即完成)。

标签: javascript angularjs promise


【解决方案1】:

$q.when 用于您不知道函数是返回承诺还是直接值的场景。

下面的例子/plunker 展示了一个方法,它的结果在 $q.all 中使用,并且每次调用它都会返回不同类型的对象(int 或 promise):

PLUNKER

app.controller('MainController', function($scope, $q, $http) {
  var count = 0;

  function doTask1() {
    var defer = $q.defer();
    $http.get('abc.json')
      .success(function (data) {
        defer.resolve(data);
      })
      .error(function () {
        defer.reject();
      });
       
    return defer.promise;
  }

  /**
   * This method will return different type of object 
   * every time it's called. Just an example of an unknown method result.
   **/
  function doTask2() {
    count++;
    var x = 99;
    if(count % 2){
      console.log('Returning', x);
      return x;
    } else {
      var defer = $q.defer();
      defer.resolve(x);
      console.log('Returning', defer.promise);
      return defer.promise;
    }
    
  }
  
  $scope.fetchData = function(){

    // At this point we don't know if doTask2 is returning 99 or promise.
    // Hence we wrap it in $q.when because $q.all expects 
    // all array members to be promises
    $q.all([
      $q.when(doTask1()),
      $q.when(doTask2())
    ])
      .then(function(results){
        $scope.results = results;
      });
      
  };
  
});
<body ng-app="myApp" ng-controller='MainController'>
  <button ng-click="fetchData()">Run</button>
  <pre>{{results|json}}</pre>
</body>

【讨论】:

    【解决方案2】:

    有没有比手动构造和解决延迟并返回承诺更简单的方法?

    是的,使用$q.when function

    doTask2: function ($scope) {
        return $q.when( 99 );
    },
    

    但是,您实际上并不需要这样做。 $q.all 将 - 尽管文档中没有说明 - 也适用于非承诺值(实现 calls _ref 转换它)。所以就

    return 99;
    

    也不错。但是,如果您事先知道它是同步的,那么使用 Promise 似乎没有多大意义。

    【讨论】:

      猜你喜欢
      • 2014-04-16
      • 1970-01-01
      • 1970-01-01
      • 2019-08-16
      • 1970-01-01
      • 2018-06-06
      • 2013-11-02
      • 2015-02-25
      • 1970-01-01
      相关资源
      最近更新 更多