Luca Trazzi
Luca Trazzi

Reputation: 1260

How can I make a waterfall Q promises?

let's take this as an example:

this is a working code, but as the array can be '1 to n' this is obviously not what I want. I need the 3 require as a waterfall, not in parallel. in the last promise, I need to resolve a final promise which is the var deferred.

require(urls[0]).then(function () {                            
    require(urls[1]).then(function () {                                
        require(urls[2]).then(function () {                                    
            deferred.resolve();
        });
    });
})

this approach is not working, because this will do 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 nice way to do this with a for/cycle?

Upvotes: 3

Views: 2873

Answers (3)

Tony
Tony

Reputation: 2483

Just to offer another way, there's a "one-line" solution to this without having to make another method:

return promises.reduce($q.when, promises[0]);

See demo here: http://plnkr.co/edit/xlGxYj57lzXdAMM5Iv6s?p=preview (I changed the default $q.when to something else to show handling each promise.)

Update: Made the plunker more representative of OP's scenario.

Upvotes: 2

KJ Price
KJ Price

Reputation: 5964

Create a function to handle the iterations:

function go (urls) {
    if (urls[0]) {
      require(urls[0]).then(function () {
          go(urls.slice(1));
      });
    }
}

go(urls);

Upvotes: 6

000
000

Reputation: 27247

Here is an excellent blog post: http://www.codeducky.org/q-serial/

I will share only 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();
});

Upvotes: 2

Related Questions