在Angular中重复使用同一个数据工厂是可行且规范的吗?

4

我正在研究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可以做到这一点,有人能发布一些示例吗?

1个回答

11

个人而言,我喜欢保持我的代码 DRY,我发现如果您在服务器API上保持通用约定,您可以通过基础工厂/存储库/类或任何您想称之为的东西来取得很长一段路。在AngularJs中,我实现这一点的方式是使用一个返回基础存储库类的AngularJs工厂,即该工厂返回一个具有原型定义而不是对象实例的JavaScript类函数,我称其为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.

I personally use Restangular so the following example is based on it, but you should be able to easily adapt this to $http or $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 继承它,但是我会省略示例,因为这超出了本问题的范围。

好东西。我对$http进行了简单的重构,以后可能会更改...一步一步来。我将OData URL基础放在具体存储库中,而不是控制器中。当然它能工作,但想知道是否推荐这样做? - ElHaix
我真的很喜欢这种方法! - beeman
很好,我正在寻找它! - Sajgoniarz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接