Reputation: 1224
I am struggling with chaining promises using $timeouts. I would like to have a "$timeout(myFunction,1000).then()" function that fires only when ALL chained timeouts returned by myFunction are resolved.
This code snippet contains different stuff I tried and I would like to achieve:
$timeout(myFunction,1000).then(function(myPromise) {
console.log("I would like this message to appear when ALL chained promises are resolved, without knowing in advance how many chained promises there are. In this case this would be after 1500 ms, not 1000ms")
myPromise.then(function()) {
console.log("with this code patern I get a message after 1500ms, which is what I want, but this does not work anymore if myOtherFunction would return a third chained $timeout")
}
})
myFunction = function() {
console.log("hi, i am launching another timeout")
return $timeout(myOtherFunction, 500)
}
myOtherFunction = function () {
console.log("1500 ms have passed")
}
How should I fix my code? Thanks!
Upvotes: 1
Views: 573
Reputation: 1224
Inspired by the answer of georgeawg I created my custom timeout function that returns the promise returned by fct, instead of the promise returned by $timeout. I did this to keep the $timeout syntax.
vm.customTimeout = function (fct, timeout){
return $timeout(fct, timeout).then(function(myReturnedPromise){
return myReturnedPromise
});
}
This function is sufficient to solve my problem above. I can chain as much customTimeouts I want.
Example :
vm.customTimeout(myFunction,1000).then(function() {
var activity1 = anyFunctionReturningAPromise(100);
var activity2 = anyFunctionReturningAPromise(1000);
return $q.all([activity1, activity2])
console.log("Without knowing the content of myFunction, I am 100% sure that
every single chained promise retuned by myFunction is resolved before
executing this code, which is quite nice!")
}).then(function(){
console.log("executes when customTimeout, activity1 & activity2 are all resolved.")
})
anyFunctionReturningAPromise = function(delay) {
return vm.customTimeout(myFunction, delay)
}
Feel free to comment what you think of it.
I hope this will be useful for someone else :)
Upvotes: 0
Reputation: 48968
Return promises to the success handler:
$timeout(null,1000).then(function() {
console.log("It is 1000ms");
var delay = 500
return myPromise(delay);
// ^^^^^^ return promise for chaining
}).then(function() {
console.log("this happens after myPromise resolves");
});
function myPromise(delay) {
promise = $timeout(null, delay);
return promise;
});
Because calling the .then
method of a promise returns a new derived promise, it is easily possible to create a chain of promises. 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. This makes it possible to implement powerful APIs.
-- AngularJS $q Service API Reference -- Chaining promises;
Upvotes: 3