Is storing variables in $ rootScope good practice?

Update 2: I found a solution

I changed the settings file only to a JS file, added var tempSettings = to the top of the file and added it to index.html. This way it loads with the initial HTML, ensuring that it will exist when app.run goes. The settings service then takes this tempSettings variable and puts it into the service. To clear, I delete the tempSettings pointer.

A new settings file called settings.js

 var tempSettings = { "environment": "development", [...] 

Added to index.html:

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

Services:

 myApp.service("settings", function(){ var settings = null; this.initialize = function() { settings = tempSettings; tempSettings = undefined; }; this.get = function() { return settings; } }); 

Update 1: I found a problem

Since the settings file is loaded by async, sometimes it happens that the module tries to use the settings before loading them. I will keep you posted on the solutions. I moved the settings to the service, which is definitely better.

Original question

When I talk about how to store environment settings in AngularJS applications, I come across options using Grunt or Gulp (and, possibly, others), but for me this option seems much more obvious. This means that there is probably a good reason not to use it. Is this way of storing settings a bad idea?

I have a file in the root of the application called settings.json that looks something like this:

 { "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" } } } 

Then I have a little in app.run that looks like this:

 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 }) }); 

And now that I need the setup, I can always go to $rootScope.settings.userApiBase or whatever. This makes sense to me, because all I have to do is make sure settings.json is ignored during registration. The whole method is really straightforward. Is there a flaw in this design?

+6
source share
2 answers

Try not to pollute $rootScope here as much as possible. Create a settings service that handles the settings. Services are singleton objects, so when you initialize service, the settings will be available wherever you enter this service.

 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; }); 

And in MyApp.run :

 MyApp.run(function (Settings) { Settings.initialize(); } 

Then, when you want to access Settings in a controller or other service or something else, just call Settings.get() , which will return your settings. Just include the Settings service in everything that uses it (for example, in the second block of code).

+9
source

In general, you should avoid rootScope pollution when possible. I like that you load the settings in app.run (). How about introducing a customization service, which is populated in app.run, and can be injected into other controllers / services? This is an added value for prototyping during unit tests.

Here is the 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 {} }) 
+3
source

Source: https://habr.com/ru/post/988107/


All Articles