在AngularJS应用程序中设计CRUD服务/工厂的最佳实践是什么,该应用程序处理单个和多个实体?
例如,我在一个名为customerFactory
的工厂中有一个customer
对象,它包含类似于以下的结构:
var customer = {
newCustomer: false,
selfUri: null,
editUri: null,
deleteUri: null,
customerName: null,
customerAddress: null
};
我在那个调用REST服务的工厂上还公开了以下示例函数:
var create = function() {
$http.post('api/customers/1', { customer: customer } );
}
var read = function() {
$http.get('api/customers', { params { uri : customer.selfUri } );
}
var update = function() {
$http.put('api/customers/1', { customer: customer } );
}
var delete = function() {
$http.delete('api/customers/1', { uri: customer.deleteUri } );
}
// This is an oddity and probably shouldn't be in this factory??
var readAll = function() {
$http.get('api/customers', {} );
}
所有这些方法基本上都适用于工厂内的customer
对象。
readAll()
方法是否应该放入另一个处理检索所有客户的服务/工厂,而不是放入上面的工厂,因为它处理单个实体?检索多个实体的REST调用是否应该放在自己的工厂中?
示例:customerFactory
// Deal with single customer entities
app.factory('customerFactory', ['$http',
function($http) {
var customerFactory = {};
var customer = {
newCustomer: false,
selfUri: null,
editUri: null,
deleteUri: null,
customerName: null,
customerAddress: null
};
var create = function() {
$http.post('api/customers/1', { customer: customer } );
}
var read = function() {
$http.get('api/customers', { params { uri : customer.selfUri } );
}
var update = function() {
$http.put('api/customers/1', { customer: customer } );
}
var delete = function() {
$http.delete('api/customers/1', { uri: customer.deleteUri } );
}
customerFactory.create = create;
customerFactory.read= read;
customerFactory.update= update;
customerFactory.create = delete;
return customerFactory;
}]);
示例:customersFactory
// Deal with multiple customer entities
app.factory('customersFactory', ['$http',
function($http) {
var customersFactory = {};
var customers = {};
var readAll = function() {
$http.get('api/customers', {} ).then(function(response) {
customers.push(response.data);
});
customersFactory.readAll = readAll;
return customersFactory;
}]);
让我在前言中说我对angular很陌生。话虽如此,您可以创建一个在CustomerList和Customer服务中使用的CustomerClass。customerlist服务将返回一个数组,而客户服务将返回单个客户。即使我用.factory()将它们添加到应用程序中,它们也被用作服务。
请注意,CustomerClass只返回没有新关键字的函数(类)。这样,您就可以在其他服务中自己实例化一个新的CustomerClass。self.init函数是构造函数,它将自动扩展您传入的对象的值。self.init在声明下自动调用。
我在工厂中使用Self.ready,所以如果我使用ng repeat,它不会显示,除非工厂的状态为ready=true。因为您是以一种ajaxy的方式提取数据,所以在收到数据并准备好之前,您不想用任何东西更新视图。
myApp.factory("CustomerClass", function ($http) {
function CustomerClass(extendableObject) {
var self = this;
self.init = function () {
//will extend newCustomer, selfUri, editUri etc... fields
angular.extend(self, extendableObject);
};
self.init();
}
return CustomerClass;
});
myApp.factory("CustomerListService", function ($http, CustomerClass) {
function CustomerList() {
var self = this;
self.ready = false;
//return array of customer objects
self.readAll = function () {
var customers = [];
$http.get('api/customers/list')
.success(function (payload) {
angular.forEach(payload.customers, function (customer) {
customers.push(new CustomerClass(customer));
});
self.ready = true;
return customers;
});
};
}
return new CustomerList;
});
myApp.factory("CustomerService", function ($http, CustomerClass) {
function Customer() {
var self = this;
self.ready = false;
//return one customer object
self.read = function (id) {
$http.get('api/customers/single', {params: {id: id}})
.success(function (payload) {
return new CustomerClass(payload);
self.ready = true;
});
};
}
return new Customer;
});
我希望您使用更适合您的$resource
。
只需要在服务中编写一个方法,就可以删除服务中的所有冗余代码,就像它将充当GET, PUT, DELETE & UPDATE
一样
工厂代码
var app = angular.module('mainApp',['ngResource']);
app.factory('Customer', function($resource) {
return $resource('/api/customers/:id'); // Note the full endpoint address
});
控制器
app.controller('CustomerController', function($scope, Customer) {
var customer = Customer.get({ id: $scope.id }, function() {
console.log(customer);
}); // get() returns a single entry
var customers = Customer.query(function() {
console.log(customers);
}); //query() returns all the customers
$scope.customer = new Customer(); //You can instantiate resource class
$scope.customer.data = 'some data';
Customer.save($scope.customer, function() {
//data saved. do something here.
}); //saves an customer. Assuming $scope.customer is the Entry object
});
通过使用单一服务方法,您可以做很多事情。在处理REST API时,我更喜欢使用$resource
有关更多详细信息,请访问此处
更新
如果你仍然想使用$http
。为了使你的代码更可重用,我将避免创建customerFactory
,因为它具有与客户相关的所有方法。我不想创建angular.constant
,通过使用该常量数组,我们将使用该数组创建一个新的服务。
常量
app.constant('customerMethods', [
{name: 'create', type: 'post', url: 'api/customers/1', dataParam:{ customer: customer }},
{name: 'read', type: 'get', url: 'api/customers', dataParam:{ params: { uri : customer.selfUri }},
{name: 'create', type: 'post', url: 'api/customers/1, dataParam:{ customer: customer }}, //you need to provide customer object
{name: 'create', type: 'post', 'api/customers/1', dataParam: { customer: customer }},//you need to provide customer object
]);
工厂
app.factory('customersFactory', ['$http', 'customerMethods', 'customer',
function($http, customerMethods, customer) {
var customersFactory = {};
var customers = {};
var customerMethods = customerMethods;
angular.forEach(customerMethods, function(val, index) {
angular.extend(customersFactory, {
val.name: function() {
return $http[val.type](val.url, val.dataParam);
}
});
});
return customersFactory;
}
]);
您重新分解的代码将如上图所示。虽然它没有经过测试,但我相信它只会是这样的。
希望这能对你有所帮助。谢谢