Lauren F
Lauren F

Reputation: 1322

AngularJS - returning promise from $http.get loop

I am making a GET request on an paginated endpoint, therefore, I am making one call, finding out how many pages the endpoint has, then looping through each page, pushing the response data from each page into one array.

However, since the call is so large, when grabbing this factory data from my controller, I've needed to put a timeout on my function to make sure all the data has come in before it is used.

I was hoping to switch this over to a promise in my factory that the controller would wait for until the request is complete. But since I am looping through each page, the way I would normally structure this doesn't work. How could I rework this to make the promise wait for the complete loop through my endpoint's pages so I can remove the timeout from my controller?

Factory API GET request

var productsData = [];
var pageNumber = 1;
var getAllProducts = function(){
    var deferred = $q.defer();
    return $http.get('/api/scroll?page=' + pageNumber,{cache: true})
        .then(function(response) {
            for (var i = response.data.results.length - 1; i >= 0; i--) {
                productsData.push(response.data.results[i]);
            };
            while (pageNumber <= response.data.pages) {
                getAllProducts();
                pageNumber++;
            }
            deferred.resolve(productsData)
            return deferred.promise;
        });
};

Controller Function

    var filterProducts;
    var getProducts = function(type, filter) {
        productFactory.getAllProducts()
        .then(function(products) {
            $timeout( function(){
                var allProducts = products;
                switch (type) {
                    case "category":
                        filterProducts = $filter('filter')(allProducts, {
                            custom: {category_code: filter}
                        });
                        break;
                    case "color":
                        filterProducts = $filter('filter')(allProducts, {
                            custom: {color_code: filter}
                        });
                        break;
                    case "season":
                        filterProducts = $filter('filter')(allProducts, {
                            custom: {season: filter}
                        });
                        break;
                    default:
                        filterProducts = allProducts;
                }
                $rootScope.products = _.sortBy(filterProducts, function(product) {
                    return product.custom.sku;
                });
            }, 1000);
        });
    };

Upvotes: 0

Views: 2201

Answers (1)

k10der
k10der

Reputation: 726

You should create a deferred object outside the GET call function and resolve it only after all requests are done. So i think it can look something like this

var productsData = [];
var pageNumber = 1;
var deferred;

function getAllProducts() {
    deferred = $q.defer();

    _getPageProducts(pageNumber);

return deferred.promise;
}
function _getPageProducts(pageNumber) {
    $http.get('/api/scroll?page=' + pageNumber,{cache: true})
        .then(function(response) {
            for (var i = response.data.results.length - 1; i >= 0; i--) {
                productsData.push(response.data.results[i]);
            };
            if (pageNumber < response.data.pages) {
                pageNumber++;
                _getPageProducts(pageNumber);
            } else {
                deferred.resolve(productsData)  ;  
            }
        });
}

Upvotes: 2

Related Questions