Objeto de serviço abstrato com cache automático para AngularJS

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