0
class UrlProvider {
    constructor(root) {
        this.root = root;
    }

    getUrl() {
        return this.root + "/api/Situations";
    }
} 


class Repository {
    constructor(urlProvider) {
        this.urlProvider = urlProvider;
    }

    getAsync() {
        var self = this;
        return httpGetAsync(self.urlProvider.getUrl()).then(function(d) {
            return d.map(x => new Situation(x));
        });
    }
}



class PromiseCacher {
    constructor(cache, promise) {
        var self = this;
        self.cache = cache;
        self.promise = promise;
    }
    runAsync() {
        var self = this;

        return self.promise().then(function (d) {
            self.cache.set(d);
            return d;
        });
    }
}

var urlProvider = new UrlProvider(appsettings.url);
var repository = new Repository(urlProvider);
var cache = new Cache();

var promiseCacher = new PromiseCacher(cache, repository.getAsync);

promiseCacher.runAsync()

When debugging the above code, chrome will crash inside the getAsync function of the repository because self.urlProvider is undefined. Inside the repository getAsync function 'this' is referring to the instance of PromiseCacher which is what actually calls it.

What's going on?

Re-writing

var promiseCacher = new PromiseCacher(cache, ()=> repository.getAsync());

makes it work as I would expect.

RoboKozo
  • 4,981
  • 5
  • 51
  • 79
  • 2
    The class doesn't *lose* a reference to `this` - it never has such a reference in the first place. The value of `this` (for ordinary, non-arrow functions) is determined solely by how the function is *called*, not where it's defined. – Pointy Oct 27 '16 at 16:35
  • And your arrow function solution is a fine one. – Pointy Oct 27 '16 at 16:35

1 Answers1

1

That's because first of all repository.getAsync is not a promise. Instead it is a function. By storing the reference of repository.getAsync to a different object property you "alter" its this value. Take a look at the following example:

var obj = {
    a: 42,
    func: function(){
        return this.a;
    }
};

obj.func();  // 42

var b = obj.func;
b();         // undefined

The example is comparable to your code:

class Repository{
    // urlProvider = ...
    getAsync (){ /* ... */ }
}

var repo = new Repository(/* ... */);
repo.getAsync();  // works

var cacher = new PromiseCacher(/* ... */);
cacher.promise = repo.getAsync;
cacher.promise();  // does not work
Derek 朕會功夫
  • 92,235
  • 44
  • 185
  • 247