简体   繁体   中英

Call a promise function multiple times until condition met from another promise function

I have the following code: http://jsfiddle.net/kyy4ey10/4/

$scope.count = 0;

function getActiveTasks() {  
    var deferred = $q.defer();
    setTimeout(function() {
        $scope.count++;
        deferred.resolve();
    },1000)
    return deferred.promise;
}

// i want to put this inside the function, but it doesn't work
var deferred = $q.defer(); 

function callPromise() {  
    getActiveTasks().then(function(){
        if($scope.count < 5){
             callPromise();
        }
        else{
            deferred.resolve()
        }
    })
    return deferred.promise;
}
callPromise().then(function(){
    $scope.count = "done"
});

If I put:

var deferred = $q.defer(); 

inside the callPromise() function, $scope.count doesn't get resolved to "done".

How can I change how I've written these two functions and then call callPromise() so I don't have to put var deferred = $q.defer(); outside?

When you declare deferred outside and recursively call your function the innermost recursive call will resolve the deferred.promise from the outside. When it's declared inside, only the inner-most promise gets resolved (but it's never returned). Consider this fiddle which kind of illustrates a similar variable scoping issue:

https://jsfiddle.net/sg6odtof/

var counter = 5;

var a = "outside";
function b() {
  //If you uncomment this, the behavior of b is different.
  //var a = "inside";
  if (counter > 0) {
    counter--;
    b();
  }

  return a;
}

alert(b());

I'm guessing you don't like that variable outside the function; therefore I think what you want to do is have the outer recursion return the inner-recursion's promise.

http://jsfiddle.net/pLns9mjw/1/

function callPromise() {  
    return getActiveTasks().then(function(){
        if($scope.count < 5) {
            return callPromise();
        }
    });
}

Also, not sure what you're trying to do for real consider $q.all which takes in an array of promises and resolves when all promises are done. As long as your tasks were known in advance, that's easy if you just want to notify when they're all done.

If the ongoing tasks is dynamic which might get added, you could $q.all them, and check to see if any are left when that promise is done until there are none left.

If you want to just do an ongoing status that reports to the user when you're at certain thresholds a timeout approach like yours is fine.

Note you should use $timeout instead of vanilla JavaScript timeouts so that any changes to the $scope don't happen outside the Angular's digest cycle.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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