0

I'm trying to "cacheify" my angular service factory. I want it to use the cache to hit the URL only the first time the page is loaded. Then when I browse to my detail page (findById) I want to use the cache. Does this make sense?

Below is what I have right now but I can't figure out a solid way to handle this async. My controller is calling into the service.

angular.module('myapp.services', [])

.factory('myservice', function ($http, $q, $cacheFactory) {

    var url = '//myurl.com/getawesomeJSON';

    return {

        findAll: function () {

            var $httpDefaultCache = $cacheFactory.get('$http');

            var data = $httpDefaultCache.get(url);
            if (data == null) {
                data = $http.get(url, { cache: true });
            }

            var deferred = $q.defer();
            deferred.resolve(data);
            return deferred.promise;
        },

        findById: function (id) {

            var data = angular.fromJson($cacheFactory.get('$http').get(url)[1]);

            for (var i = 0; i < data.length; i++) {

                if (data[i].Id === parseInt(id)) {

                    var deferred = $q.defer();
                    deferred.resolve(data[i]);
                    return deferred.promise;
                }
            }
        }
    }
});

1 Answer 1

1

I haven't tested this since you didn't provide a plunker, but the following should set you in the right direction. You need to make use of promise chaining.

angular.module('myapp.services', [])

.factory('myservice', function ($http, $q, $cacheFactory) {

    var url = '//myurl.com/getawesomeJSON';

    return {

        findAll: function () {

            var $httpDefaultCache = $cacheFactory.get('$http');

            var deferred = $q.defer();

            var data = $httpDefaultCache.get(url);
            if (!data) {
                $http.get(url, { cache: true }).then(function(result){
                    deferred.resolve(result);
                });
            } else {
                deferred.resolve(data);
            }

            return deferred.promise;
        },

        findById: function (id) {
           return this.findAll().then(function(data) {
               for (var i = 0; i < data.length; i++) {
                  if (data[i].Id === parseInt(id)) {
                      return data[i];
                  }
              }
              return $q.reject('Not found'); // id not found
           });
        }
    }
});
Sign up to request clarification or add additional context in comments.

4 Comments

Beyers thanks for the response. But wouldn't I want my findById function to return a promise too? When I call the findAll from the controller it'll need to be handled with a "then" callback. However if I call findById it'll just return the straight result. Shouldn't I be consistent?
@aherrick findById() is in fact returning a promise. Here's a reduced version to show this: return this.findAll().then(......);. So it is returning then(), and then() itself returns a promise. So calling findById() returns the promise from findAll().then(). The two inner returns are both within the successCallback of then() which we know from documentation determines if the promise should be resolved or rejected. The relevant documentation: This [then()] method returns a new promise which is resolved or rejected via the return value of the _successCallback_, _errorCallback_.
the problem im having is once the data is cached it is returned in a result like below. when it is not cached it returns differently.i.imgur.com/QaF0i1G.jpg
@aherrick Can you post a screenshot of what it looks like if it is not cached?

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.