打包功能用于解析为可重用模块

时间:2015-09-15 11:51:43

标签: javascript angularjs design-patterns angular-ui-router angular-routing

我根据John Papa's style guide(主要是)重构我的Angular应用程序,并且正在使我的应用程序更加模块化。我遇到了路线问题解决的问题。到目前为止,我使用全局app变量来保存我的Angular应用程序。我的服务也是这样的:

"use strict";
var usersService = app.service("usersService", ["$http", function ($http) {
    var userService = {};
    var endpoint = ClientSettings.authServiceUrl + "users";

    var get = function () {
        return $http.get(endpoint);
    };

    var getUser = function (id) {
        return $http.get(endpoint + "/" + id);
    };

    userService.get = get;
    userService.getUser = getUser;

    return userService;
}]);

usersService.loadUser = ["usersService", "authService", function(usersService, authService) {
    return usersService
        .getUser(authService.authentication.id)
        .then(function(response) {
            return response.data;
        });
}];

现在当我尝试重构这个时,我得到了:

(function() {
    "use strict";

    angular
        .module("App.Auth")
        .service("usersService", usersService);

        usersService.$inject = ["$http"];

    function usersService($http) {
        var endpoint = ClientSettings.authServiceUrl + "users";

        var service = {
            get: get,
            getUser: getUser
        };
        return service;     

        var get = function () {
            return $http.get(endpoint);
        };

        var getUser = function (id) {
            return $http.get(endpoint + "/" + id);
        };
    }
})();

但我遇到usersService.loadUser的问题。这是一个仅用于解析的函数:

.state("profile", {
    url : "/profile",
    controller : "profileController",
    templateUrl : "profile.html",
    resolve : {
        user : usersService.loadUser
    }
})

UsersServiceAuth模块的一部分,但路由是在应用程序所在的模块中配置的。

我希望这个模块提供一组用于解析的函数。我的目标是尽量减少代码重复,这肯定会为此做很多事情。

这是基于下面的answer by estus(它是可接受的)。

(function () {
    "use strict";

    angular
        .module("App.Auth")
        .provider("usersService", usersServiceProvider);

    function usersServiceProvider() {
        usersService.$inject = ["$http"];
        loadUser.$inject = ["usersService", "authService"];

        var provider = {
            $get: usersService,
            loadUser: loadUser
        }
        return provider;

        function usersService($http) {
            var endpoint = ClientSettings.authServiceUrl + "users";

            var service = {
                get: get,
                getUser: getUser
            };
            return service;

            var get = function () {
                return $http.get(endpoint);
            };

            var getUser = function (id) {
                return $http.get(endpoint + "/" + id);
            };
        }

        function loadUser(usersService, authService) {
            return usersService
                .getUser(authService.authentication.id)
                .then(function (response) {
                    return response.data;
                });
        }
    }
})();
  

注意:如果您正在使用ngAnnotate,则必须为注射功能手动指定/*@ngInject*/(在这种情况下为loadUser),因为它似乎不会认识到它。至少在撰写本文时。

然后,您将provider注入config函数并访问您的resolve就绪函数,如下所示:

.state("profile", {
    url : "/profile",
    controller : "profileController",
    templateUrl : "profile.html",
    resolve : {
        user : usersServiceProvider.loadUser
    }
})

这是有效的,因为虽然serviceconfig时无法使用resolve,但在解析resolve时它们仍可用。

只要它是usersServiceProviderprovider中就不需要config - 就绪函数。这是因为它是enum State{A(0),B(1)}阶段可用的唯一可注射类型的提供者。我是这样做的,因为它允许我将相关功能保存在同一个地方。

1 个答案:

答案 0 :(得分:1)

出于实际原因,在单个服务中持有解析器方法是不好的。状态在config中定义,其中没有注入usersService,即resolve进行服务注入。所以上面的代码可以用这个

resolve : {
    user : function (usersService, $injector) {
        return $injector(usersService.loadUser);
    }
}

看起来重构是错误的。

但是,这可以通过usersService provider服务来避免,因此usersServiceProvider可以注入configusersServiceProvider.loadUser可以用作解析器。

  

我的目标是尽量减少代码重复,这肯定会做到   很多。

通过在usersService中执行常规作业并将解析器保留在单独的服务中来最小化它。将loadUser打包到usersService中没有任何好处(更像是相反)。