是否有可能以良好的形式在Angular中重用相同的数据工厂?

ElH*_*aix 4 javascript factory angularjs

我正在考虑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;

}]);
Run Code Online (Sandbox Code Playgroud)

对于我的所有实体,此代码大致相同.是否可以注入实体名称(或相应的RESTful路径),如果是这样,可以将其视为部分类,如果需要其他承诺(例如遍历导航属性),它们也可以注入?

如果可以使用Angular,有人可以发布一些例子吗?

Bey*_*ers 11

就个人而言,我喜欢保持我的代码DRY,并且我发现如果你在服务器API上保持一个共同的约定,你可以使用基础工厂/存储库/类或任何你想要的它来做很长的路.我在AngularJs中实现这一点的方法是使用一个返回基本存储库类的AngularJs工厂,即工厂返回一个带有原型定义的javascript类函数,而不是一个对象实例,我称之为abstractRepository.然后,对于每个资源,我为原型继承的特定资源创建一个具体的存储库abstractRepository,因此我继承了所有共享/基本特性,abstractRepository并为具体存储库定义了任何特定于资源的特性.

我想一个例子会更清楚.让我们假设您的服务器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.
Run Code Online (Sandbox Code Playgroud)

我个人使用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;
}]);
Run Code Online (Sandbox Code Playgroud)

具体的存储库,让我们以客户为例:

app.factory('customerRepository', ['Restangular', 'abstractRepository', function (restangular, abstractRepository) {

    function customerRepository() {
        abstractRepository.call(this, restangular, 'customers');
    }

    abstractRepository.extend(customerRepository);
    return new customerRepository();
}]);
Run Code Online (Sandbox Code Playgroud)

然后在您的控制器中注入customerRepository:

app.controller('CustomerController', ['$scope', 'customerRepository', function($scope, customerRepository) {
    // Use your customerRepository
}]);
Run Code Online (Sandbox Code Playgroud)

如果你使用这个基本存储库模式你会发现你的大多数CRUD控制器也会共享很多公共代码,所以我通常创建一个我的控制器继承使用的基本CRUD控制器$injector.invoke,但我会留下一些例子因为这超出了这个问题的范围.