I have the following service:
function Configuration($http, $q) {
this.$http = $http;
this.$q = $q;
this.promises = [];
this.getEnv().then(function(d) {
this.env = d;
});
}
Configuration.prototype.getEnv = function() {
// only go get the environment setting if we don't already have it
var deferred = this.$q.defer();
if (this.promises.length > 0) {
console.log('%cAdd to queue', 'color:orange;');
this.promises.push(deferred);
} else if (!this.env) {
this.promises.push(deferred);
console.log('%cFetch from live', 'color:red');
// $http returns a promise, which has a then function, which also returns a promise
var promise = this.$http.get('config/env.json').then(function(response) {
// The then function here is an opportunity to modify the response
console.log("environment variable is " + response.data.current_environment);
// The return value gets picked up by the then in the controller.
this.env = response.data.current_environment;
var i;
for (i = this.promises.length; i--;) {
console.log('%cYay! Resolving the existing promises with a single server side request', 'color:white;background:deepskyblue');
this.promises.shift().resolve(this.env);
}
});
} else {
console.log('%cFetch direct from this.env', 'color:green');
deferred.resolve(this.env);
}
// Return the promise to the controller
return deferred.promise;
};
I am in the process of debugging the promises cache that i am building to prevent multiple hits to the server. unfortunatly the JS engine in chrome is much faster than Apache. The concept is simple, basically log the promises in a cache, if the method is hit, if there is no promise in the cache, run it, if there are promises in the cache, then don't execute it.
My problem occures in the for (i = this.promises.length; i--;) {
What happens is the this.promises is undefined. Im assuming its because its inside of a nested function and its normal JS variable scope doesn't allow it to access variables in the parent functions. But im not sure.
Is there a way I can make this work?
You can cache this
outside the $http
promise callback, because inside the callback you are no longer in your service instance's context :-
var _this = this; //<-- Here
var promise = this.$http.get('config/env.json').then(function(response) {
_this.env = response.data.current_environment;
var i;
for (i = _this.promises.length; i--;) {
_this.promises.shift().resolve(_this.env);
}
});
Or Bind the service instance's context to the callback.
this.$http.get('config/env.json').then((function(response) {
// The then function here is an opportunity to modify the response
console.log("environment variable is " + response.data.current_environment);
// The return value gets picked up by the then in the controller.
this.env = response.data.current_environment;
var i;
for (i = this.promises.length; i--;) {
console.log('%cYay! Resolving the existing promises with a single server side request', 'color:white;background:deepskyblue');
this.promises.shift().resolve(this.env);
}
}).bind(this))