6

I have create a UserService as follows:

angular.module('nrApp').factory('userService', ['Restangular', 'UserModel', 'DSCacheFactory', function (Restangular, UserModel, DSCacheFactory) {
    // Create a new cache called "profileCache"
    var userCache = DSCacheFactory('userCache', {
        maxAge: 3600000,
        deleteOnExpire: 'aggressive',
        storageMode: 'localStorage', // This cache will sync itself with `localStorage`.
        onExpire: function (key, value) {
            Restangular.oneUrl('users', key).get().then(function(data) {
                userCache.put(key, data);
            });
        }
    });

    Restangular.extendModel('users', function(obj) {
        return UserModel.mixInto(obj);
    });

    Restangular.addRequestInterceptor(function(element, operation, what, url) {
        if(operation === 'get') {
            debugger;
            //Check the cache to see if the resource is already cached
            var data = userCache.get(url);
            //If cache object does exist, return it
            if(data !== undefined) {
                angular.extend(element, data);
            }

            return element;
        }
    });

    Restangular.addResponseInterceptor(function(data, operation, what, url, response) {
        //Cache the response from a get method
        if(operation === 'get') {
            debugger;
            userCache.put(url, data);
        }

        //Unvalidate the cache when a 'put', 'post' and 'delete' is performed to update the cached version.
        if (operation === 'put' || operation === 'post' || operation === 'delete') {
            userCache.destroy();
        }

        return response;
    });

    return Restangular.service('users');
}]);

From the comments it can be seen that what I am trying to achieve is whenever a Get request is performed through this service using Restangular the local cache is checked and if the cache returns an object it is extended into the restangular element. The flow that want to achieve is that of cancelling the request to the sever when a cache object is found for that request.

However without any luck the addResponseInterceptor method still executes even though the object was found in the cache.

Are there any possible solutions to cancelling the request to the sever during a 'Get' request?

Thanks! :)

manzapanza
  • 6,087
  • 4
  • 39
  • 48
Adrian Bonnici
  • 283
  • 4
  • 14

3 Answers3

3

One way to go about it would be to cancel it via httpConfig. Restangular gives you httpConfig object as a parameter in the addFullRequestInterceptor method. You could use that like in the following:

RestangularProvider.addFullRequestInterceptor(function(element, operation, what, url, headers, params, httpConfig ) {
    ...
    if found in cache {
        var defer = $q.defer();
        httpConfig.timeOut = defer.promise;
        defer.resolve();
    }
    ...
}

Hope this helps.

CMR
  • 163
  • 5
  • Hi, the request is still being made as mentioned in this issue: https://github.com/mgonto/restangular/issues/589. – Adrian Bonnici Sep 02 '14 at 22:21
  • I created a jsfiddle since the updated code does not fit in the comment box.....http://jsfiddle.net/bop5nv1w/. Thanks :) – Adrian Bonnici Sep 02 '14 at 22:26
  • I tried using it in one of my app and it works. One difference to be noted is that, I set the logic in the angular.module('ABC').config(...) section using the RestangularProvider.addFullRequestInterceptor(...). Though I'm not sure why that would make a difference but worth trying. Unfortunately, I cannot test your code. If you could put up a working sample where you are actually making a server call, I would be glad to look into it. – CMR Sep 03 '14 at 11:32
  • it worked!...I migrated my code to my app.config and the request has been cancelled :) now all I need to do is solve the problem of injecting the DSCacheFactory into the app.config(), since its a service and not a provider the error 'Unknown Provider: DSCacheFactory' keeps being outputted in the console. I accepted your answer ;) – Adrian Bonnici Sep 03 '14 at 12:34
  • Glad it worked for you. I also edited the code to use RestangularProvider since it seems to work inside the config section. I still wonder why. Will try to find out when I'm free. Cheers. – CMR Sep 03 '14 at 15:28
1

I solved the particular issue of returning cached data if available through an angular-cache CacheFactory instance by simply changing the httpConfig settings in the RequestInterceptor. Example shown below:

angular.module('App')
.factory('Countries', function (Restangular, CacheFactory, $q) {

    var countryCache;
    var countryService;

    // Check to make sure the cache doesn't already exist
    if (!CacheFactory.get('countryCache')) {
        countryCache = CacheFactory('countryCache', { maxAge: 60 * 60 * 1000 });
    }

    if (!countryService) {
        countryService = Restangular.service('countries');

    Restangular.addFullRequestInterceptor(function(element, operation, what, url, headers, params, httpConfig) {

            if (what === 'countries') {
                switch (operation) {
                    case 'getList':
                        httpConfig.cache = countryCache;
                        break;

                    default:
                        break;
                }               
            }

            return { 
                element: element,
                headers: headers,
                params: params,
                httpConfig: httpConfig
            };

        });

    }

    return countryService;
});
0

You can decorate $http to prevent multiple request to the same url. Restangular use $http, don't need to adding fullRequestIntercepter to cancel request, because this prevent request before send.

    $provide.decorator('$http', function ($delegate, $cacheFactory, $rootScope) {
    var $http = $delegate;
    var customCache = $cacheFactory('customCache');
    var wrapper = function () {
        var key = arguments[0].url;
        var requestPromise = customCache.get(key);
        if (!requestPromise){
            $rootScope.requestCount++;
            requestPromise = $http.apply($http, arguments);
            requestPromise.then(function(){
                customCache.remove(key);
            });
            customCache.put(key, requestPromise)
        }
        return requestPromise;
    };

    Object.keys($http).filter(function (key) {
        return (typeof $http[key] === 'function');
    }).forEach(function (key) {
        wrapper[key] = function () {
            return $http[key].apply($http, arguments);
        };
    });

    return wrapper;
});

Example here

referee
  • 106
  • 3
  • 9