Here is my technique:
factory, dataService, Restangular, .
, :
.factory('identityMap',
var identityMap = {};
return {
insert: function(className, object) {
if (object) {
var mappedObject;
if (identityMap[className]) {
mappedObject = identityMap[className][object.id];
if (mappedObject) {
extend(mappedObject, object);
} else {
identityMap[className][object.id] = object;
mappedObject = object;
}
} else {
identityMap[className] = {};
identityMap[className][object.id] = object;
mappedObject = object;
}
return mappedObject;
}
},
remove: function(className, object) {
if (identityMap[className] && identityMap[className][id]) delete identityMap[className][id];
},
get: function(className, id) {
return identityMap[className] && identityMap[className][id] ? identityMap[className][id] : null;
},
flush: function(){
identityMap = {};
}
};
}
.factory('modelService', ['Restangular', 'identityMap', '$rootScope', '$log', function(Restangular, identityMap, $rootScope, $log) {
var ENUM1 = {STATE:0, OTHER_STATE:1, OTHER_STATE2: 2},
ENUM2 = {OK:0, ERROR:1, UNKNOWN:2};
function extendModel(obj, modelExtension, modelName){
angular.extend(obj, modelExtension);
obj.initExtension();
obj = identityMap.insert(modelName, obj);
}
function broadcastRestEvent(resourceName, operation, data){
$rootScope.$broadcast(resourceName + $filter('capitalize')(operation), data);
}
var resource1Extension = {
_extensionFunction1: function() {
if (this.something){
;
}
else {
}
},
publicExtensionFunction: function(param1) {
},
initExtension: function() {
this._extensionFunction2();
extendModel(this.resource2, resource2Extension, 'resource2');
}
};
var resorce2Extension = {
_extensionFunction1: function() {
},
publicExtensionFunction = function(param1) {
},
initExtension: function(){
this._extensionFunction1;
}
};
var modelExtensions = {
'resource1': resource1Extension,
'resource2': resorce2Extension
};
var rest = Restangular.withConfig(function(RestangularConfigurer) {
RestangularConfigurer.setBaseUrl('/api');
RestangularConfigurer.setOnElemRestangularized(function(obj, isCollection, what, Restangular){
if (!isCollection) {
if (modelExtensions.hasOwnProperty(what)) {
extendModel(obj, modelExtensions[what], what);
}
else {
identityMap.insert(what, obj);
}
if (obj.metadata && obj.metadata.operation) {
broadcastRestEvent(what, obj.metadata.operation, obj);
}
}
return obj;
});
RestangularConfigurer.addResponseInterceptor(function(data, operation, what, url, response, deferred) {
var newData;
if (operation === 'getList') {
newData = data.objects;
newData.metadata = {
numResults: data.num_results,
page: data.page,
totalPages: data.total_pages,
operation: operation
};
data = newData;
}
else if (operation === 'remove') {
var splittedUrl = url.split('/');
var id = splittedUrl.pop();
var resource = splittedUrl.pop();
identityMap.remove(resource, id);
broadcastRestEvent(resource, operation, id);
}
else {
data.metadata = {operation: operation};
}
return data;
});
});
return {
rest: rest,
enums: {
ENUM1: ENUM1,
ENUM2: ENUM2
},
flush: identityMap.flush,
get: identityMap.get
}
}]);
1) identityMap ( )
1:
id = Integer
field1 = String
field2 = String
resource2s = [] (List of resources2 which points to this resource with their foreign key)
2:
id = Integer
field1 = String
field2 = String
...
resource1_idfk = Foreign Key to resource 1
API , resource1 resources2 GET /api/resource1/1, , GET resource2, resource1_idfk...
, GET resource1, - GET - resource2 resource2, , resource2, resource1, ( Javascript)
,
, , , ,
, , . Angular Router UI , :
$scope. $on ( "$ destroy", function() { modelService.flush();
});
, Angular, , , / , ,
$scope.resource1instance = modelService.get('resource1', $stateParams.id);
resource1.put(...).then(
function(){
$state.go('^');
}
function(error){
handleError(error);
});
2) , `Restangular setOnElemRestangularized. , , , . , , mixin, , , . , , , factory , , factory ProposalSvc . , , , Javascript - , Restangular .
3) , , - , - Restangular, , , ng-. , , , , , $scope.on('eventName'), . , , websockets ( modelService). , - - , , websocket , , Restangular, .