Javascript 我如何使用$q做出递归承诺

Javascript 我如何使用$q做出递归承诺,javascript,angularjs,recursion,timeout,angular-promise,Javascript,Angularjs,Recursion,Timeout,Angular Promise,假设我有一条规则: var count = 0; function isCountFifty() { count++; return 50 === count; } 我想执行iscount50th()50次,每次在下次再次运行此方法之前放置一个$timeout0,直到它达到50并解决承诺 我正在尝试使用angular$q 这是总体外观: var defer = $q.defer(); defer.promise.then(resolveWhenFifty())

假设我有一条规则:

var count = 0;
function isCountFifty() {
  count++;
  return 50 === count;
}
我想执行
iscount50th()
50次,每次在下次再次运行此方法之前放置一个
$timeout
0,直到它达到50并解决承诺

我正在尝试使用angular
$q

这是总体外观:

var defer = $q.defer();
 defer.promise.then(resolveWhenFifty())
              .then(function () { ... something to do after count reaches 50 ...});
defer.resolve();
我想弄清楚这里应该是什么:

function resolveWhenFifty () {
  return function () {
    var defer = $q.defer();
    if (isCountFifty()) {
      defer.resolve();
    } else {
      $timeout(function () {
        ... ? WHAT SHOULD BE THE RECURSION HERE ? ...
      }
    }
    return defer.promise;
  }
}

我尝试了几种方法,但我一直在迷茫如何使这个递归函数以正确的解析返回正确的承诺,以及如何将所有这些承诺链接在一起。

我想这就是您要寻找的。退房

您将获得如下控制台输出:

  • 一,
  • “超时”
  • 二,
  • “超时”
  • 三,
  • “超时”
  • 。。。等等
  • 49
  • “超时”
  • 五十
  • “超时”
  • “完成”

    var self=this;
    this.isCount=函数(计数){
    控制台日志(计数);
    返回50==计数;
    }    
    var承诺=[];
    对于(var i=0;i<51;i++)promises.push({
    伯爵:我
    });
    //同步执行每个承诺
    var myFunc=函数(){
    返回承诺.reduce(函数(承诺,项){
    return promise.then(函数(){
    返回$q.when(
    $timeout(函数(){
    log('in timeout');
    },500),
    self.iscount五十(item.count));
    });
    },$q.when());
    };        
    myFunc()。然后(函数(){
    console.log('done');
    });
    

    • 我已经设法让它工作了。我在plunkr上做了一个演示

      我应该更清楚地知道,
      iscountfown()
      只是一个条件函数的示例,该函数将反复迭代,直到得到解决(超时次数最多)

      我附上以下主要概念:

        function isCountFifty() {
          count++;
          return 50 === count;
        }
      
        function delay(time) {
          return function() {
            return $timeout(angular.noop, time);
          }
        }
      
        function recursion(defer) {
          if (isCountFifty()) {
            defer.resolve();
          } else {
            var newDefer = $q.defer();
            newDefer.promise.then(delay(50)).then(function() {
              recursion(defer);
            });
            newDefer.resolve();
          }
        }
      
        var defer = $q.defer();
      
        recursion(defer);
      
        defer.promise.then(function() {
          console.log('yay! if I see this message it means I made 50 timeouts of 50 ms each');
          return defer.promise;
        });
      

      我有一个线索,这段代码可以更有效,但它做了我想要的。

      可以对代码进行重新分解,以避免使用
      $q.defer

      angular.module('myApp', []).controller('myController', function($scope, $q, $timeout) {
        var _this = this;
        var vm = $scope;
        vm.recursions = 0;
        vm.isResolved = false;
      
        var time = 200;
      
        function waitForClass(count) {
            if (count>0) { 
              vm.recursions++;
              return $timeout(function(){return waitForClass(count-1)},time);
            } else {
              return $q.when(0);
            }
        }
        waitForClass(50).then(function() {
          vm.isResolved = true;
          return 0;
        });
      });
      
      $timeout
      服务返回承诺,这些承诺可以链接起来

      因为调用承诺的
      .then
      方法会返回一个新的派生承诺,所以很容易创建一个承诺链。可以创建任意长度的链,并且由于一个承诺可以用另一个承诺解决(这将进一步推迟其解决),因此可以在链中的任何点暂停/推迟承诺的解决


      这似乎是一个XY问题。这是一个学习练习吗?如果不是,什么是真正的用例?如果不是在严格模式下调用
      参数。如果不是在严格模式下调用被调用方
      ,或者如果是在严格模式下调用
      resolveWhenFifty()
      。@charlietfl真正的用例:我有一个div。我想向它添加类x,只有在添加类x之后,我才想向它添加类y。这就是为什么我想检查dom$(element).hasClass(x){$element.addClass('y')},并且我想设置几个超时(最大计数器为10)来检查是否添加了x,然后才添加y如果使用角度方法,这将很简单。。根据数据模型设置ng类。为什么需要检查DOM而不是使用数据模型来驱动DOM中发生的事情?显示更多用于更改class@charlietfl我正在写一个指令来管理动画类。它需要将类放在特定的序列中。我假设我不能使用ng类,因为我的指令的用户可能会使用它,我不想阻止他们这样做。我不认为使用ng类或直接使用DOM有什么区别,但我可能没有意识到这些细微差别。除此之外,我正在努力学习如何履行承诺,这是一个很好的实践。感谢您的回复。我应该更清楚,这不是一个50超时,而是一个应该检查直到解决的条件(超时数未知)。我已经回答了我自己的问题——你可以明白我的意思。
      angular.module('myApp', []).controller('myController', function($scope, $q, $timeout) {
        var _this = this;
        var vm = $scope;
        vm.recursions = 0;
        vm.isResolved = false;
      
        var time = 200;
      
        function waitForClass(count) {
            if (count>0) { 
              vm.recursions++;
              return $timeout(function(){return waitForClass(count-1)},time);
            } else {
              return $q.when(0);
            }
        }
        waitForClass(50).then(function() {
          vm.isResolved = true;
          return 0;
        });
      });