Reputation: 2550
I have the following angularjs service
var assetLookUpTransformService = function($http, $q) {
this.data = null;
var self = this;
this.doStuff = function() {
var defer = $q.defer();
if (self.data) {
defer.resolve(self.data[0].DisplayName);
} else {
$http({
url: '../AssetLookup/GetAssetLookUp',
method: "GET"
}).success(function(response) {
self.data = response;
defer.resolve(self.data[0].DisplayName);
});
}
return defer.promise;
}
}
It works ok, in that once the $http request has returned all subsequent calls to "doStuff" return data from data rather than make a new request.
Then problem I have is that I am making a bunch of calls right after each other on page load. And what is happening is that the first call to doStuff will make an $http request, but also any calls to dostuff that happen before the first http request returns will also make a $http request.
Is there a way to make the calls to doStuff "wait" for the outstanding $http request to return before making there own.
Or is there a way to ensure the $http request only ever happens once?
Upvotes: 1
Views: 83
Reputation: 3651
Cache the promise, not the data. The data is encapsulated in the promise and will always be returned to whatever requests it.
var assetLookUpTransformService = function($http, $q) {
var self = this;
this.doStuff = function() {
if (!self.deferred) {
self.deferred = $q.defer();
$http({
url: '../AssetLookup/GetAssetLookUp',
method: "GET"
}).success(function(response) {
self.deferred.resolve(response[0].DisplayName);
});
}
return self.deferred.promise;
}
}
Upvotes: 3
Reputation: 414
Why don't you just make each of those calls after the first call to doStuff?
Example:
this.doStuff = function(afterRequests) {
var defer = $q.defer();
if (self.data) {
defer.resolve(self.data[0].DisplayName);
} else {
$http({
url: '../AssetLookup/GetAssetLookUp',
method: "GET"
}).success(function(response) {
self.data = response;
defer.resolve(self.data[0].DisplayName);
//make each request in here.
afterRequests.forEach(function(request) {
$http(request).success(function(response) {
//use self.data here
});
});
});
}
return defer.promise;
}
If for some reason you have to make doStuff at the same time (e.g. it's very long running), then you could use $rootScope.$broadcast to target your controllers which may need to render the data.
Upvotes: 0