javascript - 将用于解析的函数打包为可重用模块

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

我正在根据 John Papa's style guide 重构我的 Angular 应用程序(嗯,主要是)并且我正在使我的应用程序更加模块化。我遇到了路线解析的问题。到目前为止,我使用全局应用程序变量来保存我的 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);
        };
    }
})();

但是我遇到了 userService.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;
                });
        }
    }
})();

NOTE: If you're using ngAnnotate, you will have to manually specify /*@ngInject*/ for injectable functions (loadUser in this case) as it doesn't seem to recognize it. At least at the time of writing this.

然后,您将 provider 注入(inject)到 config 函数中,并访问您的 resolve-ready 函数,如下所示:

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

这是有效的,因为虽然 serviceconfig 时不可用,但它们在 resolve 正在运行时可用已解决。

只要 usersServiceProvider 是一个 provider,也不需要在 usersServiceProvider 中拥有 resolve-ready 函数。这是因为它是在 config 阶段可用的唯一可注入(inject)类型的提供程序。我这样做是因为它允许我将相关功能保留在同一个地方。

最佳答案

出于实际原因,将解析器方法保存在单个服务中是不好的。状态是在 config 中定义的,您没有注入(inject) usersService,而是使用 resolve 进行服务注入(inject)。所以上面的代码可以用这个来工作

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

看起来重构走错了路。

但是,可以通过将 usersService 设为 provider 服务来避免这种情况,因此可以将 usersServiceProvider 注入(inject)到 config 中> 和 usersServiceProvider.loadUser 可以用作解析器。

My goal is to minimize code duplication and this would certainly do a lot for that.

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

关于javascript - 将用于解析的函数打包为可重用模块,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32585374/

相关文章:

javascript - 按下提交时更改输入的样式

javascript - 为什么 $firebaseSimpleLogin :logout event execute an alert() more than once?

javascript - AngularJS:操作 `query` 的资源配置错误。预期响应包含一个对象,但得到一个数组

c# - 用具体类型覆盖抽象方法

javascript - 在按钮 id 提交之前需要检查 4 个复选框才能运行 js

JavaScript npm install Heroku,引用错误未定义

javascript - Angular Directive(指令)的属性

C++代理类

design-patterns - 域对象封装 : static methods vs Service classes

javascript - 无法获取隐藏类以使用 jquery 显示