I've expanded on Misko Heverey's excellent best-practices answer about a recommended way of accessing $http resources from a backend. Now I'm trying to figure out how to DRY it up so that I can make it reusable. It seems that few people writing reusable service components are using Misko's method of returning new Things()
that encapsulate their own server operations (like Active Record design pattern). See here and here.
The vision is a single base service that defines the CRUD functions and then child services which define a resource url and use the methods from the base service. Here's the code I'd like to break apart:
app.factory('Thing', function($http,$q) {
// constructor
var Thing = function(data) {
angular.extend(this, data);
};
var urlBase = 'https://api.resourceendpoint.com/1/class/things';
// static methods to retrieve items by id or entire list
Thing.read = function(id) {
return $http.get(urlBase + '/' + id).then(
function(response) {
// success
return new Thing(response.data);
},
function(response) {
// failure
return $q.reject(response);
}
);
};
Thing.list = function() {
return $http.get(urlBase).then(
function(response) {
// success
var items = [];
for(var i = 0; i < response.data.results.length; i++) {
items.push(new Thing(response.data.results[i]));
}
return items;
},
function (response) {
// failure
return $q.reject(response);
}
);
};
// instance CRUD methods for Thing
Thing.prototype.insert = function() {
var item = this;
return $http.post(urlBase, item).then(
function(response) {
// success
item.objectId = response.data.objectId;
return item;
},
function(response) {
// failure
return $q.reject(response);
}
);
};
Thing.prototype.update = function() {
var item = this;
return $http.put(urlBase + '/' + item.objectId, item).then(
function(response) {
// success
return item;
},
function(response) {
// failure
return $q.reject(response);
}
);
};
Thing.prototype.remove = function() {
var item = this;
return $http.delete(urlBase + '/' + item.objectId).then(
function(response) {
// success
},
function(response) {
// failure
return $q.reject(response);
}
);
};
return Thing;
});