Esta é uma pequena ferramenta excelente se você deseja ter controle sobre os serviços em cache do $ http. Ele verifica se o cache é necessário e determina a partir daí se precisa ser recarregado ou não. Isso é muito útil para feeds XHR superlentos.
Não tenho certeza se ele já usa localstorage ou não, mas isso poderia ser facilmente adicionado para torná-lo mais cache.
O serviço abstraído:
var getAbstractService = function( options ) {
var oOptions = options || {},
oServiceObject = {
_options: oOptions,
_name: 'Abstract service object',
_description: 'Returns a abstract service object which can cache out of the box.',
_cache: {
available: false,
data: {},
arguments: {}
},
_matchesCachedArguments: function() {
var i = 0,
isValid = true;
for( i in this._options.arguments ) {
if( this._options.arguments[i] !== this._cache.arguments[i] ) {
isValid = false;
}
}
return isValid;
},
_isCacheMatching: function() {
var isCacheMatching = false;
if( this._cache.available && this._matchesCachedArguments() ) {
isCacheMatching = true;
}
return isCacheMatching;
},
_loadCache: function() {
setTimeout( function() {
oServiceObject.setCallbackProcessing( {data: oServiceObject._cache.data, cached: true} );
oServiceObject._callEventEnd( oServiceObject._cache.data );
}, 1); // Avoid bugs by simulated a load time of 1ms
},
_getArgumentString: function() {
var argumentString = '',
i = 0;
for( i in this._options.arguments ) {
argumentString += '&' + i + '=' + this._options.arguments[i];
}
if( argumentString.length ) {
argumentString = '?' + argumentString.slice(1);
}
return argumentString;
},
_loadService: function() {
setLoadingState(true);
$http.get( this._options.service + this._getArgumentString() ).success( function( json ) {
oServiceObject._cache.available = true;
oServiceObject._cache.data = json;
oServiceObject._cache.arguments = {};
angular.extend(oServiceObject._cache.arguments, oOptions.arguments);
setTimeout( function() {
oServiceObject.setCallbackProcessing( {data: json, cached: false} );
oServiceObject._callEventEnd( json );
}, 1000); // simulate a 1000 ms latency
})
.error(function() {
$rootScope.$broadcast(oServiceObject._options.name + '.UPDATE', { success: false, response: false });
$rootScope.$broadcast(oServiceObject._options.name + '.ERROR', { success: false, response: false });
setLoadingState( false );
});
},
_callEventEnd: function( json ) {
$rootScope.$broadcast(this._options.name + '.UPDATE', { success: true, response: json });
$rootScope.$broadcast(this._options.name + '.SUCCESS', { success: true, response: json });
setLoadingState( false );
},
setCallbackProcessing: function( options ) {}, // Empty placeholder function to be populated by host
setServiceURL: function(url) {
this._options.service = url;
},
getService: function( args ) { // Sort of a get instance..
$rootScope.$broadcast( this._options.name + '.INIT' );
this._options.arguments = args;
console.log( this._options.name, this._cache, this._options );
console.log( 'using cache: ' + this._isCacheMatching() );
if( this._isCacheMatching() ) {
this._loadCache();
} else {
this._loadService();
}
}
};
return oServiceObject;
}
Um exemplo mais definido que envolve o serviço abstrato:
Nota: coloquei o AbstractService em um arquivo utilities js de onde o chamo. eu então o estendo em uma fábrica. Acabei de criá-lo como uma nova var para ter liberdade para criar em torno do que quero. É suposto ser superleve.
/*
Defined service from abstract caching service.
--
It first sets up the abstract service inside as a new service, not extending it.
After that it exposes the getService with some addons and returns it.
*/
angular.module( 'myApp' )
.factory( 'superService', [
'$http', '$rootScope', ''$routeParams',
function( $http, $rootScope, $routeParams ) {
'use strict';
var $service = new $utilities.getAbstractService({
name: 'SUPERSERVICE',
service: $rootScope.SERVICEPATH + 'SuperService/' + $rootScope.SERVICELANG
}),
publicApi = {
getService: function( $scope, args ) {
// Some more params
$service.getService( args );
}
};
return publicApi;
}
]);
Usei isso para quando eu tivesse que mudar de página e voltar para uma página antiga. Eu queria que isso fosse carregado da fábrica, em vez de recarregar se o serviço fosse semelhante. É principalmente para serviços compartilhados com várias páginas onde você pode acessar.
Ele também pode ser usado para implementar um armazenamento local para serviços familiares.
Saúde,
Kenneth