goodson
goodson

Reputation: 757

Cache result of parse.com promise in angular app

I'd like my objects to cache the result of some network requests and answer the cached value instead of doing a new request. This answer here done using angular promises looks a lot like what I'm going for, but I'm not sure how to express it using the Parse.com promise library. Here's what I'm trying...

module.factory('CustomObject', function() {

     var CustomObject = Parse.Object.extend("CustomObject", {

         cachedValue: null,

         getValue: function() {
             if (this.cachedValue) return Parse.Promise.as(this.cachedValue);

             return this.functionReturningPromise().then(function (theValue) {
                 this.cachedValue = theValue;
                 return this.cachedValue;
             });
         },

My idea is to return a promise whether or not the value is cached. In the case where the value is cached, that promise is resolved right away. The problem is, as I follow this in the debugger, I don't seem to get the cached result on the second call.

Upvotes: 2

Views: 400

Answers (3)

Benjamin Gruenbaum
Benjamin Gruenbaum

Reputation: 276306

Your value is almost correct. Your design is correct the only issue you have here is dynamic this.

In the context of the .then handler, this is set to undefined (or the window object), however - since you're using Parse promises and I'm not sure those are Promises/A+ compliant it can be arbitrary things - the HTTP request, or whatever. In strict code and a good promise library - that would have been an exception.

Instead, you can do CustomObject.cachedValue explicitly instead of using this:

var CustomObject = Parse.Object.extend("CustomObject", {

    cachedValue: null,

    getValue: function() {
        if (CustomObject.cachedValue) return Parse.Promise.as(this.cachedValue);

        return this.functionReturningPromise().then(function (theValue) {
            CustomObject.cachedValue = theValue;
            return this.cachedValue;
        });
    },

If $q promises are also possible instead of Parse promises, I'd use those instead:

var cachedValue = null;
getValue: function() {
    return $q.when(cachedValue || this.functionReturningPromise()).then(function(theValue){
         return cachedValue = theValue;
    });
}

Upvotes: 1

gkalpak
gkalpak

Reputation: 48211

I am not familiar with the Parse.com promise library, but it could be a plain JS error:
The this inside the function is not referring to the Promise object, but to the global object.

Change the code like that:

...
getValue: function() {
    if (this.cachedValue) return Parse.Promise.as(this.cachedValue);

    var that = this;
    return this.functionReturningPromise().then(function (theValue) {
        that.cachedValue = theValue;
        return that.cachedValue;
    });
},

Upvotes: 1

JoseM
JoseM

Reputation: 4302

You can just cache the promise and return that

module.factory('CustomObject', function() {

  var CustomObject = Parse.Object.extend("CustomObject", {

    cachedPromise: null,

    getValue: function() {
        if (!this.cachedPromise) {
            this.cachedPromise = this.functionReturningPromise();
        }
        return this.cachedPromise;
    },
  ...
  }
  ...
}

Upvotes: 1

Related Questions