4

Basically I am trying to create a promise queue in angular that works kind of like $q.all() does, except that it allows me to push more promises onto the array after $q.all() has been executed for example.

To try and explain better, imagine giving a function a single promise for which you want to execute some code for then(). However while you are waiting for this first promise to resolve, you give a second promise to the function. Now I don't want then() being called until both have completed (similar to $q.all()). If the first promise completes before the second is provided, the then() function would be called twice. This should work for an arbitrary number of promises.

Essentially you end up with a promise queue, that executes then() once for every time the queue has been emptied (i.e. all currently provided promises have been resolved). I'm sure I could figure out a nice way to do this, just seeing if anyone in SO town has already implemented something, or there is an easy option I am missing.

Matt Way
  • 32,319
  • 10
  • 79
  • 85
  • Possible duplicate of [angular $q, How to chain multiple promises within and after a for-loop](http://stackoverflow.com/questions/21024411/angular-q-how-to-chain-multiple-promises-within-and-after-a-for-loop) – fedorshishi Dec 24 '15 at 13:30
  • No it isn't! Please read the question carefully. – Matt Way Dec 24 '15 at 13:35

1 Answers1

0

I faced something similar, perhaps it would be helpful.

I needed to work through a tree via AJAX calls to build an object that represented the whole tree. When I made the AJAX call it would give me data about the child nodes which I then had to make AJAX calls to get their data. I needed to have the entire tree before I could render it, so I needed to know when I was done.

The issue with $q.all is that yes you can pass it an array of promises, but the array is fixed at that point even if you add more promises to the array later.

My (admittedly hacky) solve was to track the number of unanswered request and redo the $q.all if there were outstanding requests.

var promisesArr = [];
var unresolved = 0;

function getChildNodes(node) {
   var url = BASE_URL + '/' + node.id;
   var prom = $q(function (resolve, reject) {
            unresolved++;
            $http.get(url).then(function (resp) {
            angular.forEach(resp.data.children, function(v){
               var newNode = {};
               newNode.id = v.id;
               getChildNodes(newNode);
               node.children.push(newNode);
            });
            resolve();
            unresolved--;
            }, function () {
                // Need to handle error here
                console.log('ERROR');
                reject();
                unresolved--;
            })
         });
    promisesArr.push(prom);
}

rootNode = {id: 1}
getChildNodes(rootNode);

allResolved();

    function allResolved() {
        if (unresolved > 0) {
            $q.all(promisesArr).then(allResolved);
        } else {
            RenderTree(rootNode);
        }
    }