在Angular中,将变量存储在$rootScope中是好的实践吗?

6

更新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个回答

8

尽可能避免污染$rootScope,请创建一个处理设置的Settings服务。服务是单例对象,一旦初始化服务,设置将在您注入服务的任何地方都可用。

这里
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.get(),它将返回您的设置。只需确保将Settings服务注入到使用它的任何地方(就像我在第二个代码块中所做的那样)。


1
我不明白“不污染$rootScope”的原因。你能提供任何阅读链接吗? - Jeeva J

3
通常情况下,应尽可能避免污染rootScope。我喜欢你在app.run()中加载设置。不妨引入一个SettingsService,在app.run中填充,并可以注入到其他控制器/服务中?这样做的附加价值是在单元测试期间可以进行模拟。
这里有一个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 {}
})

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接