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

时间:2015-07-29 18:20:39

标签: javascript angularjs dependency-injection module

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")总是返回false,无论应用程序中是否定义了Application常量:

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

1 个答案:

答案 0 :(得分:0)

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

(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

虽然仍然对批评或更好的解决方案持开放态度!