将变量存储在$ rootScope良好实践中吗?

时间:2015-05-28 16:25:39

标签: angularjs application-settings

更新2:我找到了解决方案

我已将设置文件更改为JS文件,将var tempSettings =添加到文件的开头,并将其添加到index.html中。这样它就会加载初始HTML,确保它在app.run运行时就会存在。然后,设置服务获取此tempSettings变量并将其放入服务中。要清理,我删除了tempSettings指针。

名为settings.js

的新设置文件
var tempSettings = {
  "environment": "development",
[...]

添加到index.html:

<script src="settings.js"></script>

服务:

myApp.service("settings", function(){
  var settings = null;

  this.initialize = function() {
    settings = tempSettings;
    tempSettings = undefined;
  };

  this.get = function() {
    return settings;
  }

});

更新1:我发现了一个问题

由于设置文件是异步加载的,因此有时会发生模块在加载之前尝试使用这些设置。我会告诉你最新的解决方案。我已将设置移至服务中,这肯定更好。

原始问题

当我谷歌如何在AngularJS应用程序中存储环境设置时,我遇到了使用Grunt或Gulp的选项(并且可能还有其他选项),但对我来说这个选项似乎更为明显。这意味着可能有充分的理由不使用它。这种存储设置的方式是不是一个坏主意?

我在我的应用程序根目录中有一个名为settings.json的文件,它看起来像这样:

{
  "settingsFile": true,
  "environment": "development",
  "logLevel": "debug",
  "userApiBase": "http://localhost/covlelogin/web/api/",
  "oAuth": {
    "google":{
      "endpoint": "https://accounts.google.com/o/oauth2/auth",
      "clientId": "12345",
      "scope": "email profile",
      "state": "MyToken123",
      "redirectUri": "http://localhost/loginadmin/web/oAuthRedirect",
      "responseType": "code",
      "approvalPrompt": "force"
    }
  }
}

然后我在app.run中有一点看起来像这样:

MyApp.run(function ($rootScope, $http) {
  //Load settings
  $http.get('settings.json').
      success(function (settings) {
        if (settings.settingsFile){
          $rootScope.settings = settings;
          console.log("Settings loaded");
        }else{
          console.log("Error loading settings. File may be corrupt.");
          //Additional error handling
        }
      }).
      error(function (data) {
        console.log("Error getting settings file.");
        //Additional error handling
      })
});

现在每当我需要设置时,我总能去$rootScope.settings.userApiBase或其他什么。这对我来说很有意义,因为我所要做的就是确保在办理登机手续时忽略settings.json。整个方法非常简单。这个设计有缺陷吗?

2 个答案:

答案 0 :(得分:9)

尽量不要污染sfController Here。创建一个处理设置的设置服务。服务是单例对象,因此一旦您$rootScope服务,设置将在您注入服务的任何位置都可用。

initialize

MyApp.service("Settings", function($http) { var settings = null; this.initialize = function() { $http.get('settings.json').success(function (s) { if (s.settingsFile){ settings = s; console.log("Settings loaded"); } else { console.log("Error loading settings. File may be corrupt."); //Additional error handling } }).error(function (data) { console.log("Error getting settings file."); //Additional error handling }) }; this.get = function() { return settings; } return this; });

MyApp.run

然后,只要您想在控制器或其他服务中访问MyApp.run(function (Settings) { Settings.initialize(); } ,只需致电Settings即可返回您的设置。只需确保将Settings.get()服务注入任何使用它的服务(就像我在第二个代码块中所做的那样)。

答案 1 :(得分:3)

通常,应尽可能避免污染rootScope。我喜欢你在app.run()中加载设置。如何引入在app.run中填充的SettingsService,并将其注入到其他控制器/服务中?这具有在单元测试期间可模拟的附加值。

这是plunker

app.run(function(SettingsService) {
  SettingsService.name = "Alex";
  SettingsService.password = "pw1";
})

app.controller('MainCtrl', function($scope, SettingsService) {
  $scope.settings = SettingsService;
});

app.factory('SettingsService', function() {
  return {}
})