我如何参数化模块,以便它可以按需配置需要它的应用程序?

How can I parameterize a module so that it can configure the applications that require it on demand?

关于 harvested framework 的模式,我想将我的 AngularJS 应用程序的配置和实用程序分解为一个独立的模块,例如:

angular.module("configurer", [])
.config(["$httpProvider", function($httpProvider) {

  $httpProvider.defaults.headers.common["Accept"] = "application/hal+json";

}]);

然后,在我的应用程序中:

angular.module("app", ["configurer"]);

我想添加一个可选 CSRF 保护:

angular.module("configurer", [])
.config(["$httpProvider", function($httpProvider) {

  $httpProvider.defaults.headers.common["Accept"] = "application/hal+json";

  if (applicationWantsCsrfProtection) {
    // implement CSRF protection
  }

}]);

问题是,如何设置这个applicationWantsCsrfProtection变量?


我尝试遍历常量:

angular.module("configurer", [])
.config(["$injector", "$httpProvider", function($injector, $httpProvider) {

  $httpProvider.defaults.headers.common["Accept"] = "application/hal+json";

  if ($injector.has("Application")) {
    var Application = $injector.get("Application");
    if (Application.hasOwnProperty("CSRF")) {
      // implement CSRF protection with Application.CSRF.* attributes
    }
  }

}]);

然后,在我的应用程序中:

angular.module("app", ["configurer"])
.constant("Application", {
  CSRF: {
    headerName: "X-CSRF-TOKEN",
    cookieName: "APP-CSRF-TOKEN"
  }
});

但是$injector.has("Application")总是returnsfalse,不管Application常量是否在应用程序中定义:

http://plnkr.co/edit/8RFwqvs6Tmp9gpGkUq7W?p=preview

我通过提供商找到了解决方案:

(function(angular) {

  var config = function($injector) {
    console.log("configurer config has Application: " + $injector.has("Application")); // true
  };

  var run = function($injector) {
    console.log("configurer run has Application: " + $injector.has("Application")); // true
  };

  angular.module("configurer", [])

  .provider("init", function() {
    return {
      config: config,
      $get: function() {
        return {
          run: run
        }
      }
    }
  });

})(angular);

然后,在应用程序中:

angular.module("app", ["configurer"])

  .constant("Application", {
    CSRF: {
      headerName: "X-CSRF-TOKEN",
      cookieName: "APP-CSRF-TOKEN"
    }
  })

  .config(function(initProvider, $injector) {
    initProvider.config($injector);
  })

  .run(function(init, $injector) {
    init.run($injector);
  });

http://plnkr.co/edit/c301t8TN8TfWcn52Kit2?p=info


此解决方案的一个优点是配置器子模块可以在不修改应用程序的情况下扩展配置器行为:

(function(angular) {

  var config = function($injector) {
    console.log("subConfigurer config has Application: " + $injector.has("Application")); // true
  };

  var run = function($injector) {
    console.log("subConfigurer run has Application: " + $injector.has("Application")); // true
  };

  angular.module("subConfigurer", ["configurer"])

  .config(function(initProvider) {

    var configCallfront = initProvider.config;    
    initProvider.config = function($injector) {
      configCallfront($injector);
      config($injector);
    };

    var runCallfront = initProvider.$get().run;
    initProvider.$get = function() {
      return {
        run: function($injector) {
          runCallfront($injector);
          run($injector);
        }
      }
    };

  });

})(angular);

http://plnkr.co/edit/GQKcMK7RkTEwK0YEfAiW?p=info


但仍然欢迎批评或更好的解决方案!