1

I want to wait for a service $http result before the controller does the rest. I tested some hardcoded JSON for myData and it IS visible in the controller, but as soon as I try to populate myData with a $http request, the controller is not waiting for it and just walks thru the rest of the code. The network tab from Chrome webdevelopper is showing the expected result for the request.

I already have the following:

var ListerApp = angular.module('ListerApp',[
    'ListerAppFilters',
    'sharedFactoryApp',
    'sharedServiceApp',
    'ListerAppController',
    'infinite-scroll',
    'angular-inview',
    'ngRoute'
]);

ListerApp.config(['$routeProvider', '$httpProvider', function($routeProvider, $locationProvider) {
    $routeProvider
        .when('/list',
            {
                templateUrl: '/assets/services/partials/list.html',
                controller: 'ListerCtrl',
                resolve : {
                    'sharedServiceAppData': function($sharedServices){
                        // sharedFactoryAppData will also be injectable in your controller, if you don't want this you could create a new promise with the $q service
                        return $sharedServices.promise();
                    }
                }
            }
        );
}]);

angular.module('sharedServiceApp', []).service('$sharedServices', ['$http', '$rootScope', '$q', function($http, $rootScope, $q) {
    var myData = null;

   return {
        promise : function () {
            if (!myData) {
                $http({method : 'GET', url : '/shop/api/json', params : {
                        end         : $rootScope.endmarkerSyncDataset,
                        page        : 1,
                        per_page    : $rootScope.itemsPerPage
                    }
                }).success(function (data) {
                    myData = data.data_set;
                    //deferred.resolve(data.data_set);
                });

                // I allready tested this and this is OK: myData = {foo : 'bar'};
            }
        },
        getShopData: function () {
            return myData;
        }
    };
}]);

(function(){
    var appController = angular.module('ListerAppController', []);

    appController.controller('ListerCtrl', ['$scope', '$rootScope', '$http', '$filter', '$timeout', '$sharedFactories', '$sharedServices',
        function($scope, $rootScope, $http, $filter, $timeout, $sharedFactories, $sharedServices) {
            $scope.items = $sharedServices.getShopData();
            console.log($scope.items); // return myData -> null
        }
})();

2 Answers 2

3

I've done this a bunch of times here's what I usually do in my resolve object for the routeProvider, need to make sure you return all promises appropriately in order for the route change to wait on resolve properties.

 $routeProvider
    .when('/path',
        {
            templateUrl: 'some/path/to/template.html',
            controller: 'myCtrl',
            resolve : {
                'myData': ['mySrvc',function(mySrvc){
                    return mySrvc.someMethod().then(function(response){
                        return response.data;
                    },function(){
                        return {};
                    });
                }]
            }
        }
    );

Then the service:

angular.module('myApp.services').factory('mySrvc',['$http',function($http){
    var _url = 'https://someurl.com/path/to/api';

    return {
        someMethod : function(vars){
            if(angular.isDefined(vars)){
                return $http.post(_url,$.param(vars),{headers:{'Content-Type':'application/x-www.form-urlencoded'}});
            }else{
                return $http.get(_url);
            }
        }
    };
}]);

Then in the controller you need to inject the resolve parameters at the end of the parameter list for the controller.

angular.module('myApp.controllers').controller('myCtrl',['$scope','myData',function($scope,myData){

});

In your code, in the resolve object of the routeProvider you have a return from a function that returns nothing, try returning the promise from the $http and then the data.data_set value in the success function of your service.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for your help. I have found something and posted it below. Your example helps me further to create an api-like object.
0

I have found something like $q.defer, resolve and promise. It holds up everything until the status "promise" is reached.

Here's a link

angular.module('sharedServiceApp', []).service('$sharedServices', ['$http', '$rootScope', '$q', function($http, $rootScope, $q) {
    var myData = null;

    return {
        promise : function () {
            if (!myData) {
               var deferred = $q.defer();
               $http({method : 'GET', url : '/shop/api/json', params : {
                    end         : $rootScope.endmarkerSyncDataset,
                    page        : 1,
                    per_page    : $rootScope.itemsPerPage
                }
            }).success(function (data) {
                myData = data.data_set;
                deferred.resolve(data.data_set);
            }).error(function(data, status, headers, config) {
                deferred.reject("Error: request returned status " + status); 
            });
            return deferred.promise;
        } else {
            return myData;
        }
    },
    getShopData: function () {
        return myData;
    },
    setShopData: function (data) {
        myData= data;
    }
};

}]);

1 Comment

You really don't need to use $q in this instance as $http already returns a promise. Just return the promise from your $http call and then in your success and error functions make sure you return the data or error status.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.