在 AngularJS 中创建 CRUD 服务的最佳实践

Best practices for creating CRUD services in AngularJS

在处理单个多个实体的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;

    }]);

我希望您使用更适合您情况的 $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

要了解更多详细信息,请执行 visit here

更新

如果你仍然想坚持使用 $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;

    }
]);

重构后的代码将如上所示。虽然没有测试过,但我相信只有这样的方式。

希望对您有所帮助。谢谢。

首先让我说我是 angular 的新手。话虽如此,您可以创建一个在 CustomerList 和 Customer 服务中使用的 CustomerClass。客户列表服务将 return 一个数组,而客户服务将 return 单个客户。即使我使用 .factory() 将它们添加到应用程序中,它们也被用作服务。

请注意,CustomerClass 仅 return 没有新关键字的函数 (class)。这样您就可以在其他服务中自行实例化一个新的 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;
});