I've implemented a cacheService that has method get(url) which gets the value from HTTP, puts it to localStorage and returns $q promise. On the next .get(url) run it gets value from localStorage and returns it wrapped with $q.
function get(url){
var saved = JSON.parse(localStorage.getItem(url));
if (angular.isObject(saved)){
return $q.when(saved);
}
return $http.get(url).then(function(xhr){
localStorage.setItem(url, JSON.stringify(xhr.data));
return xhr.data;
});
}
Here's a case when my method doesn't work - it makes more than 1 HTTP request.
If I call cacheService.get(url) twice (e.g. from different modules):
And I don't like it.
So the question is:
how to syncronise requests by url to have only 1 request per url?
UPD: I've got an idea:
var currentRequests = {};
currentRequests[url]
is empty, do the request and set currentRequests[url] = $http.get(url)
- store the promise in currentRequsts[url]
isn't empty, then this request is running now, then just return currentRequests[url]
;As JS is run in a single thread in browsers, currentRequests is thread-safe. But it isn't in nodejs. Correct?
What do you think about it?
It might be not that good solution. but you can give it a try.
I'll suggest you to maintain the array of promises.
var promiseArr = [];
function get(url){
var saved = JSON.parse(localStorage.getItem(url));
if (angular.isObject(saved)){
return $q.when(saved);
}
//check if $http request for the url has a pending promise.
if(!promiseArr.hasOwnProperty(url)){
promiseArr[url] = $http.get(url).then(function(xhr){
localStorage.setItem(url, JSON.stringify(xhr.data));
delete promiseArr[url]; //Delete the promise once resolved.. please check.
return xhr.data;
});
}
return promiseArr[url]; //return the promise from the array.
}