如何使用$ q

时间:2016-02-27 12:54:43

标签: javascript angularjs recursion timeout angular-promise

让我说我有这条规则:

var count = 0;
function isCountFifty() {
  count++;
  return 50 === count;
}

我希望执行isCountFifty() 50次,每次在下次再次运行此方法之前放置$timeout 0,直到达到50并解析承诺。

我试图使用角度$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;
  }
}

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

3 个答案:

答案 0 :(得分:1)

可以重新考虑代码以避免使用$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服务返回承诺,这些承诺可以链接

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

1

答案 1 :(得分:0)

我认为这是你正在寻找的东西。查看working CodePen

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

  • 1
  • "在超时"
  • 2
  • "在超时"
  • 3
  • "在超时"
  • ......等......
  • 49
  • "在超时"
  • 50
  • "在超时"
  • "完成"

      var self = this;
    
      this.isCountFifty = function(count) {
        console.log(count);
        return 50 === count;
      }    
      var promises = [];
    
      for (var i = 0; i < 51; i++) promises.push({
        count: i
      });
    
      // execute each promise synchronously
      var myFunc = function() {
        return promises.reduce(function(promise, item) {          
          return promise.then(function() {
            return $q.when(
              $timeout(function() {
                console.log('in timeout');
              },500),
              self.isCountFifty(item.count));
          });
        }, $q.when());
     };        
     myFunc().then(function() {
       console.log('done');
     });
    

答案 2 :(得分:0)

我设法让它发挥作用。我在plunkr上做了一个演示。

https://plnkr.co/edit/MQS6n9qKOfGMxYwMQ8H3?p=preview

我应该更清楚isCountFifty()只是一个条件函数的示例,它将一次又一次地迭代直到被解析(具有最大超时次数)。

我附上以下主要概念:

  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;
  });

我有一个线索,这段代码可以更有效率,但它可以满足我的需求。