Angular $q 多项承诺

Angular $q multiple promises

我正在尝试这样做:

  1. 运行 乐趣 1
  2. 然后在 fun1 returns(承诺解决)之后,运行 fun2 和 fun3 并行(异步)
  3. 然后在 fun2、3 return(承诺解决)之后,运行 一些具有不同输入的 fun4 全部并行
  4. 然后最终 运行 fun5 在所有 fun4 都被解析之后。

        $q.all({
            fun1: fun1()
        }).then(function(){
    
            return $q.all({
                fun2: fun2(),
                fun3: fun3(),
            });
    
        }).then(function(){
    
            var promises = [];
    
            for(var i = 0; i < 3; i += 1){
                promises.push(fun4(i));
            }
    
            return $q.all(promises);
    
        }).then(function(){
            fun5();
        });
    

fun 1~5都是api调用类似这种模式:

var funX = function(){
        return $http({
            method: 'GET',
            url: '/someURL'
        }).success(function(data, status, headers, config) {
            return;

        }).error(function(data, status, headers, config) {
            return new Error();
        });
    };

我想确保它们 运行 按照我上面描述的顺序排列。看起来 fun4 没有等待 fun2 和 fun3 到 return,fun5 也没有等待所有 fun4 到 return。

正如我之前所说,可能发生的情况是您的某些 Promise 出现故障。防止 $http Promise 失败的最佳方法是处理 .catch() 中的错误(不要使用 .success().error() 作为它们已被弃用)和 return 一个 truthy 值。

以下是一个试图模拟您的进程失败的测试用例(打开控制台并查看记录的内容):

angular.module('Test', [])
  .controller('Ctrl', function($q, Factory) {
    $q.all({
        fun1: Factory.succeedFunc('1')
      })
      .then(function() {
        return $q.all({
          fun2: Factory.failingFunc('2'),
          fun3: Factory.succeedFunc('3')
        });
      })
      .then(function() {
        var promises = [];
        for (var i = 0; i < 3; i++) {
          promises.push(Math.random() > 0.5 ? Factory.failingFunc('4: ' + i) : Factory.succeedFunc('4: ' + i));
        }
        return $q.all(promises);
      })
      .then(function() {
        Factory.succeedFunc('5');
      });
  })
  .factory('Factory', function($q, $timeout) {
    return {
      failingFunc: function(msg) {
        var deferred = $q.defer();
        console.log('executing', msg);
        $timeout(function() {
          console.log('failed', msg);
          deferred.reject();
        }, 500);
        return deferred.promise;
      },
      succeedFunc: function(msg) {
        var deferred = $q.defer();
        console.log('executing', msg);
        $timeout(function() {
          console.log('succeeded', msg);
          deferred.resolve();
        }, 1000);
        return deferred.promise;
      }
    };
  });
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="Test" ng-controller="Ctrl">
</div>

这是当你处理拒绝和 return Promises' .catch() 中的值时发生的情况(尽管要小心不要将 .catch() 因为这也会拒绝新创建的 Promise:

angular.module('Test', [])
  .controller('Ctrl', function($q, IgnoreErrors) {
    var Factory = IgnoreErrors;
    $q.all({
        fun1: Factory.succeedFunc('1')
      })
      .then(function() {
        return $q.all({
          fun2: Factory.failingFunc('2'),
          fun3: Factory.succeedFunc('3')
        });
      })
      .then(function() {
        var promises = [];
        for (var i = 0; i < 3; i++) {
          promises.push(Math.random() > 0.5 ? Factory.failingFunc('4: ' + i) : Factory.succeedFunc('4: ' + i));
        }
        return $q.all(promises);
      })
      .then(function() {
        Factory.succeedFunc('5');
      });
  })
  .factory('Factory', function($q, $timeout) {
    return {
      failingFunc: function(msg) {
        var deferred = $q.defer();
        console.log('executing', msg);
        $timeout(function() {
          console.log('failed', msg);
          deferred.reject();
        }, 500);
        return deferred.promise;
      },
      succeedFunc: function(msg) {
        var deferred = $q.defer();
        console.log('executing', msg);
        $timeout(function() {
          console.log('succeeded', msg);
          deferred.resolve();
        }, 1000);
        return deferred.promise;
      }
    };
  })
  .factory('IgnoreErrors', function(Factory) {
    return {
      failingFunc: function(msg) {
        return Factory.failingFunc(msg).catch(function() {
          return true;
        });
      },
      succeedFunc: function(msg) {
        return Factory.succeedFunc(msg).catch(function() {
          return true;
        });
      }
    }
  });
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="Test" ng-controller="Ctrl">
</div>

所以我能够通过使用新的 api 解决这个问题并摆脱弃用的 errorsuccess.