Search code examples
javascriptangularjspromiseqdeferred

Run request until response is what was requested with $q


I have this plunker to illustrate my problem:

http://plnkr.co/edit/tsBy2K0xv6bboBlZRM8c

$scope.start = function() {

  runThisUntil("Ok");
  //here I would like to do this:
  //runThisUntil("Ok").then(function () {
  //doSomeStuff()  
  //});

}

$scope.clear = function() {
  $scope.responses = [];
}

function runThisUntil(criteria) {

  runThis(criteria);



}

function runThis(criteria) {
  run().then(function (response) {
    if (response == criteria) {
      $scope.responses.push("Done");
    } else {
      $scope.responses.push("Wait");
      runThisUntil(criteria);
    }
  });
}


var okWhen = 10;
var start = 0;
function run() {

  var deferred = $q.defer();
  $timeout(function () {
    if (start !== okWhen) {
    start += 1;
    deferred.resolve("Bad");
  } else {
    deferred.resolve("Ok")
    start = 0;
  }
  }, 100);


  return deferred.promise;


}
}

What I'm trying to simulate here is form of loop where I do requests to an http server that does work in batches and respondes with "There is still more work" until "Work is done".

When I tried to do this with promises I ended up creating new deferred promises with $q so the initial promise I was waiting for to be resolved never got resolved because the request was repeated which I do by executing the same function that I am in again if it's not done.

--Edit I figured I could do this with a $scope.$broadcast() when it's done, but I would like to solve this by using $q if possible and not listen to events if possible.


Solution

  • UPDATE:

    var app = angular.module('myApp', []);
    
    angular.module('myApp').controller('TestCtrl', ["$timeout", "$interval", "$scope", "$q", function TestCtrl($timeout, $interval, $scope, $q) {
    
      activate();
    
      $scope.responses = [];
    
      function activate() {
    
        $scope.start = function() {
    
          runThisUntil("Ok").then(function() {
            $scope.responses.push("Pushed final");;
          });
        }
    
        $scope.clear = function() {
          $scope.responses = [];
        }
    
        function runThisUntil(criteria) {
    
          return runThis(criteria);
        }
    
        function runThis(criteria) {
          return run().then(function (response) {
            $scope.responses.push("Done");
          }, function () {
            $scope.responses.push("Wait");
            return runThis(criteria);
          });
        }
    
    
        var okWhen = 10;
        var start = 0;
        function run() {
    
          var deferred = $q.defer();
          $timeout(function () {
            if (start !== okWhen) {
            start += 1;
            deferred.reject("Bad");
          } else {
            deferred.resolve("Ok")
            start = 0;
          }
          }, 100);
    
          return deferred.promise;
        }
    
      }
    
    
    }]);
    

    http://plnkr.co/edit/MYn6otWMmxHFDd41jBpI?p=preview