-1

I would like that the for loop will be executed and then the result will be sent over the next function:

FindIdsRequests =  function(){
    results = $scope.requests
    var deferred = $q.defer();
    var promise = deferred.promise;
    var array = []
    for (var i in results) {
        promise = promise.then(function(){
            array.push(results[i].uid)      
        })
        return promise
    }
    return promise.then(function(){
        return array
    })
}

$scope.ConfirmRequests = function(){
    //alert('req'+JSON.stringify($scope.requests))
    FindIdsRequests().then(function(array){
        alert('arr'+JSON.stringify(array))
    })
})

the FindIdsRequests function should return the result of the for loop however there is no return (the alert is not printed so does not arrive there). Any idea?

asasa178
  • 221
  • 1
  • 11

5 Answers5

2

You can take advantages of $q insted of returning a promise like so:

$q.all([promise1, promise2]);

For example:

FindIdsRequests =  function(){

    var requests = $scope.requests;
    var results = [];    
    var array = [];

    for (var i in requests) {

        var req = $http.get('http://someUrl.com/' + requests[i].uid);

        array.push(req);

        req.then(function (response) {
            results.push(response.data);
        });
    }

    return $q.all(array).then(function(){
        return results;
    });
}

This code will return a promisse of all promisses in the array to be resolved.

lenilsondc
  • 9,590
  • 2
  • 25
  • 40
  • `$q.all` resolves if and only if all promises in the array are resolved. So then, if any of the promises fail to resolve, $q.all also fails. – lenilsondc Oct 07 '16 at 15:44
  • this won't work ... final `return` will never be reached and array is not an array of promises and nothing resolves `promise` so array will always be empty – charlietfl Oct 07 '16 at 15:44
  • yes it doesn't work @charlietfl can you please write a solution? thanks – asasa178 Oct 07 '16 at 15:50
  • It doesn't work because you are asking for people to produce a solution for a code that doesn't evem make sense. Sorry but, I simply can't guess what your code is suposed to do. So I've updated my answer with a proper example of how using `$q.all` can solve your problem. But write it up is up to you mate, good luky. – lenilsondc Oct 07 '16 at 15:59
  • new answer is better but you don't need `var deferred = $q.defer();` ... just return `$q.all` ... the extra promise is an anti-pattern – charlietfl Oct 07 '16 at 16:02
  • Well I think I need a promise to do that. The method must return a promise that resolves an array of results. `$q.all` doesn's serve for that purpose. I mean, it could be in a different situation where a result wouldn't make difference, but in this case I have to produce a result that is an array. Don't you think? – lenilsondc Oct 07 '16 at 16:06
  • since you are using `$http` successful requests will resolve each promise in array of promises , and returning `$q.all(array)` would resolve after all requests resolve. So just doing `return $q.all(arr).then(function(){ return results;})` would pass the results to next `then` – charlietfl Oct 07 '16 at 16:11
  • Oh sure! I understand what you saying now. Well, you can update the answer and participate if you like. Will you? – lenilsondc Oct 07 '16 at 16:17
  • you should be able to handle that – charlietfl Oct 07 '16 at 16:19
2

Problems:

  1. You are overwriting promise in each iteration of loop... so there is only ever one promise
  2. There is no resolve of promise to ever trigger then() so the array will always be empty
  3. You have a return in the loop so the loop will break on first iteration and never complete
  4. If this were asynchronous i will not be what you think it is inside then() as it will have reached it's end before the promise resolves

I see no need to write this up in code since everything you are doing is synchronous and shows no need for promise in the first place

charlietfl
  • 170,828
  • 13
  • 121
  • 150
  • for point 4: do you think that if I define the variable before then will be fine? look at my answer. – asasa178 Oct 07 '16 at 16:04
  • No you need a closure. See http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example – charlietfl Oct 07 '16 at 16:06
0

Ok thanks also to the comments of @charlietlf the following code works:

FindIdsRequests =  function(){

    results = $scope.requests
    var deferred = $q.defer();
    var promise = deferred.promise;
    var array = []
    for (var i in results) {
        alert('www'+JSON.stringify(results[i].uid))
        var obj = results[i].uid
        promise = promise.then(function(){
            array.push(results[i].uid)      
        })
        //return promise
    }
    deferred.resolve(array)
    return promise.then(function(){
            alert('ee'+JSON.stringify(array))
            return array
     })
}

essentially I forgot to put the resolve.

asasa178
  • 221
  • 1
  • 11
0

Creating a Chain of Promises from an Array of Promises

Use $.when to create an empty promise and use a for loop to create a chain:

function chainPromiseArray(promiseArray){
    var promise = $q.when();
    var array = [];
    for (var i=0;  i < promiseArray.length; i++) {
        promise = promise.then(function(){
            var derivedPromise = promiseArray[i].then(function(result) {
                //push data
                array.push(result.data);
            });
            //return promise to chain
            return derivedPromise;
        });
    };
    var finalPromise =  promise.then(function(){
        return array;
    });
    return finalPromise;
};

The above example starts with an empty promise, then chains from that empty promise. The final promise will resolve to the array created by the chain.

Chaining promises

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

The example executes the promises sequentially. To execute the promises in parallel use the $q.all method.

georgeawg
  • 48,608
  • 13
  • 72
  • 95
  • This is all fine and dandy except the OP's `FindIdsRequests()` function has no async components and thus can just be a regular function and does not need promises at all. Using promises is just complicating something that can be quite simple. – jfriend00 Oct 07 '16 at 23:08
0

Your FindIdsRequests() function has no async elements in the code as shown so it can just be a synchronous function and, in fact, trying to use promises in it is just complicating a very simple operation:

// get an array of uid from $scope.requests
function FindIdsRequests() {
    return $scope.requests.map(function(item) {
        return item.uid;
    });
});

$scope.ConfirmRequests = function() {
    var ids = FindIdsRequests();
    console.log('arr: '+ JSON.stringify(ids));
})
jfriend00
  • 683,504
  • 96
  • 985
  • 979