Angular-cache w/$http example issues

446 views
Skip to first unread message

James Johnson

unread,
Jun 14, 2014, 12:25:25 AM6/14/14
to angula...@googlegroups.com
Hey,

I'm having several issues with the Angular-cache w/$http examples.
  • Missing $q on the service declaration.
  • In the "own caching while using the $http service" example, where is the data put into the cache?

Thanks, Jim

Jason Dobry

unread,
Jun 14, 2014, 1:02:07 AM6/14/14
to angula...@googlegroups.com
Hmm, looks like the example is missing a line. Can't believe no one caught this before...

Should be:

  1. $http.get('api/data/' + id).success(function (data) {
  2. console.log('time taken for request: ' + (new Date().getTime() - start) + 'ms');
  3. dataCache.put(id, data);
  4. deferred.resolve(data);
  5. });

James Johnson

unread,
Jun 14, 2014, 9:23:39 AM6/14/14
to angula...@googlegroups.com

That is what I thought.  Thanks.

Also, my example works the first time and the view displays on the first init of the controller.  Unfortunately, after routing away and returning, the view doesn't display.  It looks like the cache code is working.  Is this a situation of I need to wait using a resolve?

Jim

Jason Dobry

unread,
Jun 14, 2014, 1:14:47 PM6/14/14
to angula...@googlegroups.com
I don't think I can answer your question without seeing your example. Angular-cache is synchronous, there should be no need for resolve.

James Johnson

unread,
Jun 14, 2014, 7:43:17 PM6/14/14
to angula...@googlegroups.com

I'm clearly doing something wrong (stupid).  Here is my service and controller.  It works the first-time but not navigating back, it doesn't.  Suggestions:

.service('rackService', function ($http, DSCacheFactory, $q) { // added $q

        DSCacheFactory('dataCache', {
            maxAge: 900000, // Items added to this cache expire after 15 minutes.
            cacheFlushInterval: 3600000, // This cache will clear itself every hour.
            deleteOnExpire: 'aggressive' // Items will be deleted from this cache right when they expire.
        });

        return {
            getData: function (id) {
                var deferred = $q.defer(),
                    start = new Date().getTime(),
                    dataCache = DSCacheFactory.get('dataCache');

// Now that control of inserting/removing from the cache is in our hands,
// we can interact with the data in "dataCache" outside of this context,
// e.g. Modify the data after it has been returned from the server and
// save those modifications to the cache.

                if (dataCache.get(id)) {
                    console.log('time taken from cache: ' + (new Date().getTime() - start) + 'ms');
                    deferred.resolve(dataCache.get(id));
                } else {
                    $http.get('https://rack').success(function (data) {

                        console.log('time taken for request: ' + (new Date().getTime() - start) + 'ms');
                        dataCache.put(id, data);
                        deferred.resolve(data);
                    });
                }
                return deferred.promise;
            }
        };
    })

-------------------------

.controller('RackCtrl', function($scope, $state, $ionicViewService, $http, $location, rackService) {

        // This a temporary solution to solve an issue where the back button is displayed when it should not be.
        // This is fixed in the nightly ionic build so the next release should fix the issue

        $ionicViewService.clearHistory();

        var load = function() {

            console.log('call rack load(1)');

            $scope.rackdata = [];

            rackService.getData(1)
                .then(function (data) {
                    $scope.rackdata = data;
                    console.log('service then');
                });

            console.log('after service, next is rackdata');
            console.log($scope.rackdata);
.............

Jason Dobry

unread,
Jun 14, 2014, 11:13:20 PM6/14/14
to angula...@googlegroups.com
Your rackService looks totally fine, excepting that you don't handle any possible error with the $http.get call. The controller code you posted is incomplete, so I'm not sure what else is going on there. The following line in the controller:

console.log($scope.rackdata);

$scope.rackdata will always be undefined because the rackService.getData call is asynchronous, so the console.log will happen before you actually have the data.

I see the ionic framework is handling you view routing. I have never used the framework, so I can't advise on whether there's an issue with how you're using their routing functionality. 

What you're doing with angular-cache looks good though.

James Johnson

unread,
Jun 15, 2014, 12:09:36 AM6/15/14
to angula...@googlegroups.com

I guess that is the issue, that on the second pass the $scope.rackdata is undefined.  Any suggestions?

Here is the complete controller:


.controller('RackCtrl', function($scope, $state, $ionicViewService, $http, $location, rackService) {

        // This a temporary solution to solve an issue where the back button is displayed when it should not be.
        // This is fixed in the nightly ionic build so the next release should fix the issue

        $ionicViewService.clearHistory();

        var load = function() {

            console.log('call rack load(1)');

            $scope.rackdata = [];

            rackService.getData(1)
                .then(function (data) {
                    $scope.rackdata = data;
                    console.log('service then');
                });

            console.log('after service, next is rackdata');
            console.log($scope.rackdata);

            // from http://www.pseudobry.com/building-large-apps-with-angular-js/
            /*$scope.$watch(function () {
                return rackService.getData(1);
            }, function () {
                $scope.rackdata = rackService.getData(1);
            });*/

        }

        load();

        // called just before the scope is deleted,
        $scope.$on("$destroy", function() {
            console.log("Rack destroyed");
        });

        // Navigation methods

        $scope.selected = function(index) {
            $location.path('/app/toc/' + index);
        }

    })

James Johnson

unread,
Jun 15, 2014, 12:29:43 AM6/15/14
to angula...@googlegroups.com
Strange behavior.  Annotation in red.

First time through:

"call rack load(1)" controllers.js:629
"after service, next is rackdata" controllers.js:640
[] controllers.js:641  <--- rackdata undefined at this point due to async
"time taken for request: 85ms" services.js:80
"service then" controllers.js:636
[Object, Object, Object, Object, Object, Object, Object, Object, Object] controllers.js:63  <--- rackdata in service execution then

View displays
Route off and return

"call rack load(1)" controllers.js:629
"time taken from cache: 0ms" services.js:76
"after service, next is rackdata" controllers.js:640
[] controllers.js:641  <--- rackdata undefined at this point due to async
"service then" controllers.js:636
[Object, Object, Object, Object, Object, Object, Object, Object, Object] controllers.js:637  <--- rackdata in service execution then

But this time, view doesn't display correct.

Same pattern of execution except pass 2 using the cache.

It is as if the view doesn't see the rackdata.  It must be an issue with ionic nav back somehow.

Jim

James Johnson

unread,
Jun 15, 2014, 12:41:39 AM6/15/14
to angula...@googlegroups.com
This issue is clearly related to the cache.  If I comment out the cache.get portion of the service, it works fine.  Thoughts?

Commented out cache.get version of the service.


.service('rackService', function ($http, DSCacheFactory, $q) { // added $q

        DSCacheFactory('dataCache', {
            maxAge: 900000, // Items added to this cache expire after 15 minutes.
            cacheFlushInterval: 3600000, // This cache will clear itself every hour.
            deleteOnExpire: 'aggressive' // Items will be deleted from this cache right when they expire.
        });

        return {
            getData: function (id) {
                var deferred = $q.defer(),
                    start = new Date().getTime(),
                    dataCache = DSCacheFactory.get('dataCache');

// Now that control of inserting/removing from the cache is in our hands,
// we can interact with the data in "dataCache" outside of this context,
// e.g. Modify the data after it has been returned from the server and
// save those modifications to the cache.

                /*if (dataCache.get(id)) {

                    console.log('time taken from cache: ' + (new Date().getTime() - start) + 'ms');
                    deferred.resolve(dataCache.get(id));
                } else {*/

                    $http.get('https://rack').success(function (data) {
                        console.log('time taken for request: ' + (new Date().getTime() - start) + 'ms');
                        dataCache.put(id, data);
                        deferred.resolve(data);
                    });
                //}
                return deferred.promise;
            }
        };
    })

James Johnson

unread,
Jun 15, 2014, 1:21:22 AM6/15/14
to angula...@googlegroups.com
Could it be the structure of my data?  I'm using ngMockE2E to mock the http interface.

var rackdata = [

//          entityId of the playlist owner

            {playlistId: '1', entityId: '1',
                coverTitle: ' Abstract this is a test and more of a test and a third test',
                bmc: 'Nike Bike',
                username: 'Jim',
                coverSrc: 'http://lorempixel.com/300/500/abstract',
                postImageSrc: 'http://lorempixel.com/300/500/abstract'},
            {playlistId: '2', entityId: '2',
                coverTitle: 'City',
                bmc: 'Trek Bike',
                username: 'Marc',
                coverSrc: 'http://lorempixel.com/300/500/city',
                postImageSrc: 'http://lorempixel.com/300/500/city'},
            {playlistId: '3', entityId: '3',
                coverTitle: 'People',
                bmc: 'New Balance Shoes',
                username: 'Chris',
                coverSrc: 'http://lorempixel.com/300/500/people',
                postImageSrc: 'http://lorempixel.com/300/500/people'},
            {playlistId: '4', entityId: '4',
                coverTitle: 'Transport',
                bmc: 'Delta',
                username: 'Ryan',
                coverSrc: 'http://lorempixel.com/300/500/transport',
                postImageSrc: 'http://lorempixel.com/300/500/transport'},
            {playlistId: '5', entityId: '5',
                coverTitle: 'Fashion',
                bmc: 'Target',
                username: 'MaryRose',
                coverSrc: 'http://lorempixel.com/300/500/fashion',
                postImageSrc: 'http://lorempixel.com/300/500/fashion'},
            {playlistId: '6', entityId: '6',
                coverTitle: 'Technics',
                bmc: 'Sony',
                username: 'Jim',
                coverSrc: 'http://lorempixel.com/300/500/technics',
                postImageSrc: 'http://lorempixel.com/300/500/technics'},
            {playlistId: '7', entityId: '7',
                coverTitle: 'Sports',
                bmc: 'Titlest',
                username: 'Jim',
                coverSrc: 'http://lorempixel.com/300/500/sports',
                postImageSrc: 'http://lorempixel.com/300/500/sports'},
            {playlistId: '8', entityId: '8',
                coverTitle: 'Nightlife',
                bmc: 'Coors',
                username: 'Chris',
                coverSrc: 'http://lorempixel.com/300/500/nightlife',
                postImageSrc: 'http://lorempixel.com/300/500/nightlife'},
            {playlistId: '9', entityId: '9',
                coverTitle: 'Nature',
                bmc: 'Tents',
                username: 'MaryRose',
                coverSrc: 'http://lorempixel.com/300/500/nature',
                postImageSrc: 'http://lorempixel.com/300/500/nature'}

        ];

Jason Dobry

unread,
Jun 15, 2014, 1:39:41 AM6/15/14
to angula...@googlegroups.com
I don't see anything wrong with the structure of your data, and the cached data is clearly making it to your controller.  You may need to call $scope.$apply() after you get the data. At some point they removed the automatic triggering of $digest loops for $http service calls. 

James Johnson

unread,
Jun 15, 2014, 10:57:36 AM6/15/14
to angula...@googlegroups.com
I was thinking the same thing. 

It is interesting that if I comment out the cache in my service, thus using the http path only, It works every time.  Therefore, that infers that the implementation of the service and it's usage is correct.

Will continue to research.  Thanks again for your help, very much appreciated.

James Johnson

unread,
Jun 15, 2014, 11:47:12 AM6/15/14
to angula...@googlegroups.com
I have eliminated your cache as the issue.  I'm using deckgrid (https://github.com/akoenig/angular-deckgrid) to provide a masonry view.  If I replace that with a simple ng-repeat, I can see the data in the view.

Jason Dobry

unread,
Jun 15, 2014, 12:51:01 PM6/15/14
to angula...@googlegroups.com
Good to hear.
Reply all
Reply to author
Forward
0 new messages