How can I make waterfall Q promises?
let's take this as an example:
- I have 3 urls in url array
- The require function returns a promise that just calls $ http
this is working code, but since the array can be from 1 to n, this is clearly not what I want. I need 3 to be required as a waterfall and not in parallel. in the last promise I need to resolve the final promise that is deferred by var.
require(urls[0]).then(function () {
require(urls[1]).then(function () {
require(urls[2]).then(function () {
deferred.resolve();
});
});
})
this approach doesn't work because it will make all the $ http calls in parallel.
var promises = [];
angular.forEach(urls, function (value) {
promises.push(require(value));
});
$q.all(promises).then(function () {
deferred.resolve();
});
Is there a good way to do this with a for / cycle?
source to share
Here's a great blog post: http://www.codeducky.org/q-serial/
I will only share the part that is relevant.
First, we define this helper method:
function serial(tasks) {
var prevPromise;
angular.forEach(tasks, function (task) {
//First task
if (!prevPromise) {
prevPromise = task();
} else {
prevPromise = prevPromise.then(task);
}
});
return prevPromise;
}
Then we use it.
serial([
function() { return require(urls[0]) },
function() { return require(urls[1]) },
function() { return require(urls[2]) }
]).then(function () {
deferred.resolve();
});
source to share
Just to suggest another way, a "one-line" solution without using another method:
return promises.reduce($q.when, promises[0]);
See a demo here: http://plnkr.co/edit/xlGxYj57lzXdAMM5Iv6s?p=preview (I've changed the default $q.when
to something else to show how each promise is processed.)
Update: Made the plunker a more personable OP script.
source to share