【问题标题】:Angular $q multiple promisesAngular $q 多个承诺
【发布时间】:2015-12-15 14:35:43
【问题描述】:

我正在尝试这样做:

  1. 跑酷1
  2. 然后在 fun1 返回(promise 解决)后,并行运行 fun2 和 fun3(异步)
  3. 然后在 fun2, 3 返回(promises resolve)之后,使用不同的输入并行运行一些 fun4
  4. 然后在所有 fun4 都解决后最终运行 fun5。

        $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 返回,fun5 也没有等待所有 fun4 返回。

【问题讨论】:

  • 粗略一瞥看起来还不错。您将$q.all 用于fun1 的任何原因?
  • 如果只是一个承诺,可能不需要所有的东西,但即使我想只有一个承诺,一切都应该工作?
  • 我无法重现该问题(使用$timeout)~plnkr.co/edit/8cFEkMbrc08S1K6vLupi?p=preview。一切似乎都按所需的顺序执行
  • 另外,success 和 error 方法已被弃用 ~ docs.angularjs.org/api/ng/service/$http#deprecation-notice
  • 我在 v1.4.7 上,我正在监视控制台,看起来不像是因为触发解析的错误。可能是因为我使用的是旧的success 和error。将使用then 进行测试。

标签: angularjs promise angular-promise


【解决方案1】:

所以我能够通过使用新的 api 解决这个问题并摆脱不推荐使用的 error 和 success。

【讨论】:

    【解决方案2】:

    正如我之前所说,可能发生的情况是您的某些Promises 失败了。防止$http Promises 失败的最佳方法是处理.catch() 中的错误(不要使用.success() 和.error(),因为它们已被弃用)并返回一个 真实价值。

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

    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>

    当您处理拒绝并在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>

    【讨论】:

    • “返回一个真实值” ~ 这完全不正确
    • 谢谢,菲尔,现在修好了。我正在考虑在.catch() 中抛出一个错误。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-18
    • 2015-02-25
    • 2015-05-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多