Zaki Zaki - 3 months ago 34
AngularJS Question

Angular Promise - $q.all not returning result and calling Post method several times not working

Am trying to call a

Post
method and then depending on the result I am going to call same
Post
method multiple times and return the result, using $q.all.

My
Post
method is :

getData: function (params, callback) {
$http.post('service/myService', params)
.success(function (data) {
callback(null, data);
}).error(function (error) {
callback(error);
});
}


I am calling it in below function, this function is recursive so if it contains
nextUrl
I am doing same thing until there is no object for
paging
:

var result = [];
var promises = [];
var checkForPaging = function (nextUrl, service, $q) {
var deferred = $q.defer();
var criteria = {
url: url
}
var promise = service.getData(criteria, function (error, data) {
if (data.statusCode == 200) {
for (var i = 0; i < data.body.items.length; i++) {
result.push(data.body.items[i]);
}
if (data.body.paging != null && data.body.paging.next != null) {
checkForPaging(data.body.paging.next.url, service, $q);
} else{
deferred.resolve(result);
}
}
});

promises.push(promise);
$q.all(promises)
return deferred.promise;
}


Then am calling this function from below and want to get the
result
back once all calls are complete:

checkForPaging(data.body.paging.next.url, myService, $q).then(function (data) {
console.log(data)
});


The issue I am having is that it never hits the callback function above :
console.log(data)
. But I can see it calling the
Post
method several times.

If I resolve it like below then I can see after first
Post
it is hitting the callback above:

$q.all(promises).then(function (results) {
deferred.resolve(result);
}, function (errors) {
deferred.reject(errors);
});


Am I doing it right? How can I get the result back and call the Post method several times?

Let me know if it is not clear or have any questions!

Answer

Here is solution: https://plnkr.co/edit/HqkFNo?p=preview I rewrited logic a bit. You can catch the main idea.

UPDATE added promiseless solution

1) Your service should return only promise:

this.getData = function(url, params){
    return $http.post(url, params); //You're just returning promise
}

2) You don't need $q.all, you can use single promise:

var result = [];

var deferred;

var checkForPaging = function (url) {

    if(!deferred){
        deferred = $q.defer();
    }

    //resolvind service promise
    newService.getData(url).then(
        //if ok - 200
        function(response){
            for (var i = 0; i < data.body.items.length; i++) {
                result.push(data.body.items[i]);
            }

            if (data.body.paging != null && data.body.paging.next != null){
            {
                return checkForPaging(data.body.paging.next.url);
            } else{
               deferred.resolve(result);
            }
        },
        //handle errors here
        function(error) {

        }
    );

    return deferred.promise;
}

3) You should call it like this:

checkForPaging('url').then(function(data){
    //here will be resolved promise
    console.log(data);
});
Comments