简体   繁体   English

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

[英]How can I make a recursive promise with $q

let's say I have this rule: 假设我有这个规则:

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

I want to perform isCountFifty() 50 times and each time put a $timeout 0 before the next time I run this method again until it reaches 50 and resolves the promise. 我想执行isCountFifty() 50次,每次将$timeout 0放在下一次我再次运行此方法之前,直到达到50并解决了promise。

I'm trying to achieve it using angular $q 我正在尝试使用角度$q实现它

This is the general look: 这是一般外观:

var defer = $q.defer();
 defer.promise.then(resolveWhenFifty())
              .then(function () { ... something to do after count reaches 50 ...});
defer.resolve();

I'm trying to figure out what should be here: 我试图弄清楚这里应该是什么:

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

I've tried several ways but I keep getting lost on how to make this recursive function that returns the right promises with right resolves, and how do I chain all these promises together. 我尝试了几种方法,但是我对如何使此递归函数返回正确的承诺和正确的解决方案以及如何将所有这些诺言链接在一起感到迷惑。

I've managed to make it work. 我设法使它起作用。 I made a demo on plunkr. 我在plunkr上进行了演示。

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

I should have been more clear that the isCountFifty() is just an example for a condition function that will iterate again and again until resolved (with a max number of timeouts). 我应该更清楚地知道isCountFifty()只是条件函数的一个示例,该函数将一次又一次地迭代直到解决(具有最大超时数)。

and I'm attaching the main concept below: 并且我附上以下主要概念:

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

I have a clue that this code can be more efficient but it does what I want. 我有一个线索,说这段代码可以更有效,但是可以满足我的要求。

The code can be re-factored to avoid using $q.defer . 可以重构代码以避免使用$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;
  });
});

The $timeout service returns promises and those promises can be chained . $timeout服务返回承诺,这些承诺可以被链接

Because calling the .then method of a promise returns a new derived promise, it is easily possible to create a chain of promises. 因为调用promise的.then方法会返回新的派生promise,所以很容易创建promise的 It is possible to create chains of any length and since a promise can be resolved with another promise (which will defer its resolution further), it is possible to pause/defer resolution of the promises at any point in the chain. 可以创建任何长度的链,并且由于一个承诺可以用另一个承诺来解决(这将进一步推迟其解决方案),因此可以在链中的任何点暂停/推迟对承诺的解决。 1 1

The DEMO on PLNKR . DENK在PLNKR上

I think this is what you're looking for. 我认为这就是您要寻找的。 Check out working CodePen . 正常工作的CodePen

You'll get a console output like this: 您将获得如下控制台输出:

  • 1 1
  • "in timeout" “超时”
  • 2 2
  • "in timeout" “超时”
  • 3 3
  • "in timeout" “超时”
  • ... etc ... ...等等...
  • 49 49
  • "in timeout" “超时”
  • 50 50
  • "in timeout" “超时”
  • "done" “完成”

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM