Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular service cache a value

My service needs to retrieve a value asynchronously, but once I have it, I'd like to used a cached version of the value.

When two controllers call this service, I'd expect the first one to cache the retrieved value and the second one to use the cached value, but according to the log, I never find a cached value. When this runs, I see a log message that shows the value being cached, then, when I follow an angular route to a different controller, I do not see that the service finds the cached value. Why does it not run according to my expectation**?**

angular.module('myApp.services').factory('Config', function() {

    var Config = { };

    Config.currentYear = function() {
        if (Config._currentYear) {
            // sadly, we never execute here
            console.log("returning cached year");
            return Parse.Promise.as(Config._currentYear);
        }
        return Parse.Config.get().then(function(config) {
            console.log("caching year");
            Config._currentYear = config.get("currentYear");
            return Config._currentYear;
        });
    };

    return Config;

});

A couple notes: (1) I named the cached attribute _currentYear, adding the underscore to avoid colliding with the function name. Not sure if I need to do that. (2) I return a fulfilled promise when the value is cached, so the function always returns a promise...also not sure if that's needed, but figure it can't hurt.

like image 670
user1272965 Avatar asked Oct 20 '22 19:10

user1272965


1 Answers

Instead of caching the data, why don't you just cache the promise and return it. When you cache the data, you are setting the data Config._currentYear only within the success callback and there are chances that other subsequent call(s) happening before the success callback is run. So you end up making the same call again. You can easily see this when you have calls made to the same service method from different controllers which are instantiated, by their presence on the same template. Caching a promise upfront will avoid these issues.

angular.module('myApp.services').factory('Config', function() {
    var config; //Just use to save the promise
    Config.currentYear = function() {
        /*If there is already a call made before return the promise else
          make the actual call and store the promise in the variable.*/
        return config || config = Parse.Config.get().then(function(config) {
            return config.get("currentYear");
        });
    };
});
like image 98
PSL Avatar answered Oct 22 '22 09:10

PSL