I've wrote a pretty useful method to prevent multiple requests per single get
url. There is a well known pattern - to store promise and return it for each next request. But there is too much copy/paste for my taste. So, please check my solution. Maybe you can give me advice to make it better or maybe point at any mistakes.
Here it is (working plunker):
promisedService.$inject = ['$q', '$http', '$httpParamSerializer'];
function promisedService($q, $http, $httpParamSerializer){
var promisesInProgress = {};
return {
singleGet: singleGet
}
/**
* you can pass:
* url
* url and callback function
* url, params and callback function
*/
function singleGet(url){
var params, preResolve;
if(arguments.length == 3){
preResolve = arguments[2];
params = arguments[1];
}
else if(arguments.length == 2){
if(typeof arguments[1] === 'function'){
preResolve = arguments[1];
}
else {
params = arguments[1]
}
}
// creating unique key based on URL + params
var requestUrl = _buildUrl(url, params);
// checking for promise. If promise already exists - returning it
if(promisesInProgress.hasOwnProperty(requestUrl)) {
return promisesInProgress[requestUrl];
}
// else - saving new promise
var deferred = $q.defer();
promisesInProgress[requestUrl] = deferred.promise;
// sending a request
$http.get(url, params).then(function(response){
console.log('server request');
// if callback was passed, wrapping it in promise and returning
// why do we need a callback. In case we need to cache data
if(preResolve){
$q.when(preResolve(response)).then(function(data){
deferred.resolve(data);
});
}
else
//else - returning data as is
deferred.resolve(response);
delete promisesInProgress[requestUrl];
}, function(error){
deferred.reject(error);
delete promisesInProgress[requestUrl];
});
return deferred.promise;
}
/////////////////////////////// PRIVATE /////////////////////////////////
function _buildUrl(url, params) {
var serializedParams = $httpParamSerializer(params);
if (serializedParams.length > 0) {
url += ((url.indexOf('?') === -1) ? '?' : '&') + serializedParams;
}
return url;
}
}