1

I have a service that must return to me countries list. But I want to cache country values to a variable to prevent multiple ajax calls. I have created a promise object but my html must call this service multiple times. When i call the service, sometimes it returns from ajax first time after that it returns from cache, sometimes it retruns from ajax 3 times after that cache. How can I handle this?

Here is my service:

var vm = this;
vm.countries;

 vm.getCountries = function () {
    var q = $q.defer();
        if (vm.countries === undefined) {
            return $http({
                method: 'POST',
                cache: true,
                url: API + '/api/Global/Countries',
            }).then(function successCallback(response) {
                if (errorHandler(response.data)) {
                    vm.countries = response.data;
                    q.resolve(response.data)
                    console.log("ajax")
                    return q.promise;
                }
            });
        } else {
            console.log("cache")
            q.resolve(vm.countries)
            return q.promise;
        }
}
2
  • Try to remove the return statement in front of $http. You should also handle the error and return q.promise if errorHandler returns false. Commented Jul 11, 2016 at 9:16
  • if i remove the return, i get "TypeError: Cannot read property 'then' of undefined" error in console. Commented Jul 11, 2016 at 9:18

3 Answers 3

3

Return q.promise in all circumstances

vm.getCountries = function () {
    var q = $q.defer();
        if (vm.countries === undefined) {
            return $http({
                method: 'POST',
                cache: true,
                url: API + '/api/Global/Countries',
            }).then(function successCallback(response) {
                if (errorHandler(response.data)) {
                    vm.countries = response.data;
                    q.resolve(response.data)
                    console.log("ajax")

                }
            });
        } else {
            console.log("cache")
            q.resolve(vm.countries)
        }

         return q.promise;
}
Sign up to request clarification or add additional context in comments.

1 Comment

Does it work? What will happen if you call vm.getCountries() twice? I mean, if I call the same function before resolving the $http request.
2

You can cache the promise instead of the data. You may also want to consider what would happen in the error case here. The cached promise would need to be cleared.

var vm = this;

function getCountries () {
    if (!vm.countryPromise) {
        vm.countryPromise = $http({
            method: 'POST',
            cache: true,
            url: API + '/api/Global/Countries',
        }).then(function successCallback(response) {
            if (errorHandler(response.data)) {
                console.log("ajax")
                return response.data;
            }
        });
    } else {
        console.log("cache")
    }
    return vm.countryPromise;
}

2 Comments

I will add the error function after that, thanks a lot!
I have to improve your solution. Could you please check my other question too? stackoverflow.com/questions/38308915/…
1

If you are using it for binding the values to the templates. I think, it could be achieved using $resource also.

angular.module('myApp').factory('Country', function($resource) {
  return $resource(API + '/api/Global/Countries'); 
});

//in controller
var countries= Country.query(function() {
  console.log(countries);
});

quote from resource's documentation

It is important to realize that invoking a $resource object method immediately returns an empty reference (object or array depending on isArray). Once the data is returned from the server the existing reference is populated with the actual data. This is a useful trick since usually the resource is assigned to a model which is then rendered by the view. Having an empty object results in no rendering, once the data arrives from the server then the object is populated with the data and the view automatically re-renders itself showing the new data. This means that in most cases one never has to write a callback function for the action methods.

https://docs.angularjs.org/api/ngResource/service/$resource

https://www.sitepoint.com/creating-crud-app-minutes-angulars-resource/

Comments

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.