我正在考虑Angular的CRUD通用工厂(我目前优先使用服务):
app.factory('dataFactory', ['$http', function ($http) {
var urlBase = '/odata/ContentTypes';
// The _object_ defined in the factory is returned to the caller, rather than as with a service,
// where the _function_ defined in the service is returned to the caller
var dataFactory = {};
dataFactory.getContentTypes = function () {
var contentTypes = $http.get(urlBase);
return contentTypes;
};
dataFactory.getContentType = function (id) {
return $http.get(urlBase + '/' + id);
};
dataFactory.insertContentType = function (contentType) {
return $http.post(urlBase, contentType);
};
dataFactory.updateContentType = function (contentType) {
return $http.put(urlBase + '/' + contentType.ID, contentType);
}
dataFactory.deleteContentType = function (id) {
return $http.delete(urlBase + '/' + id);
}
// to traverse navigation properties
//dataFactory.getUserFromContentTypeId = function (id) {
// return $http.get(urlBase + '/' + id + '/user');
//}
//dataFactory.getOrders = function (id) {
// return $http.get(urlBase + '/' + id + '/orders');
//};
return dataFactory;
}]);
对于我的所有实体,此代码大致相同。是否可以注入实体名称(或相应的RESTful路径),如果是这样,可以将其视为部分类,如果需要额外的承诺(例如遍历导航属性),它们也可以被注入?
如果可以使用Angular,有人可以发布一些例子吗?
答案 0 :(得分:11)
就个人而言,我喜欢保留我的代码DRY,并且我发现如果你在服务器API上保持一个共同的约定,你可以在基础工厂/存储库/类或任何你想要的任何方面走很长的路打电话给它。我在AngularJs中实现这一点的方法是使用一个返回基本存储库类的AngularJs工厂,即工厂返回一个带有原型定义而不是对象实例的javascript类函数,我称之为abstractRepository
。然后,对于每个资源,我为原型继承自abstractRepository
的特定资源创建一个具体的存储库,因此我继承了abstractRepository
的所有共享/基本功能,并为具体存储库定义了任何特定于资源的功能。 / p>
我认为一个例子会更清楚。让我们假设您的服务器API使用以下URL约定(我不是最纯粹的REST,因此我们将约定保留到您想要实现的任何内容):
GET -> /{resource}?listQueryString // Return resource list
GET -> /{resource}/{id} // Return single resource
GET -> /{resource}/{id}/{resource}view // Return display representation of resource
PUT -> /{resource}/{id} // Update existing resource
POST -> /{resource}/ // Create new resource
etc.
我个人使用Restangular,因此以下示例基于此,但您应该能够轻松地将其调整为$http
或$resource
。
<强> abstractRepository 强>
app.factory('abstractRepository', [function () {
function abstractRepository(restangular, route) {
this.restangular = restangular;
this.route = route;
}
abstractRepository.prototype = {
getList: function (params) {
return this.restangular.all(this.route).getList(params);
},
get: function (id) {
return this.restangular.one(this.route, id).get();
},
getView: function (id) {
return this.restangular.one(this.route, id).one(this.route + 'view').get();
},
update: function (updatedResource) {
return updatedResource.put();
},
create: function (newResource) {
return this.restangular.all(this.route).post(newResource);
}
// etc.
};
abstractRepository.extend = function (repository) {
repository.prototype = Object.create(abstractRepository.prototype);
repository.prototype.constructor = repository;
};
return abstractRepository;
}]);
具体的存储库,我们以客户为例:
app.factory('customerRepository', ['Restangular', 'abstractRepository', function (restangular, abstractRepository) {
function customerRepository() {
abstractRepository.call(this, restangular, 'customers');
}
abstractRepository.extend(customerRepository);
return new customerRepository();
}]);
然后在你的控制器中注入customerRepository
:
app.controller('CustomerController', ['$scope', 'customerRepository', function($scope, customerRepository) {
// Use your customerRepository
}]);
如果使用此基本存储库模式,您会发现大多数CRUD控制器也将共享许多公共代码,因此我通常会创建一个基本CRUD控制器,我的控制器继承使用$injector.invoke
,但我会留下这个问题的例子,因为它超出了这个问题的范围。