Angular: загрузить свойства среды перед настройкой / запуском

Я разрабатываю угловое приложение, и у этого приложения есть около 10 настраиваемых свойств (в зависимости от среды и клиента).

У меня были эти свойства в конфигурационных файлах json, но это действительно хлопотно: должны быть определенные сборки для env/company. Поэтому я хотел бы получить эти свойства один раз из бэкэнда при загрузке приложения.

Таким образом, чтобы сделать это, я создал провайдера

var app = angular.module('myApp', [...]);
app.provider('environment', function() {
    var self = this;
    self.environment;

    self.loadEnvironment = function (configuration, $http, $q) {
        var def = $q.defer();
        $http(...)
        .success(function (data) {
            self.environment = Environment.build(...);
            def.resolve(self.environment);
        }).error(function (err) {
            ...
        });
        return def.promise;
    };

    self.$get = function(configuration, $http, $q) {
        if (!_.isUndefined(self.environment)) {
            return $q.resolve(self.environment);
        }
        return self.loadEnvironment(configuration, $http, $q);
    };
}
app.config(... 'environmentProvider', function(... environment) {
    ...
    //The problem here is that I can't do environment.then(...) or something similar... 
    //Environment does exists though, with the available functions... 
}

Как правильно работать с этим провайдером, который выполняет вызов rest для заполнения его переменной среды?

Заранее спасибо!

1 ответ

Решение

Это отличный сценарий для изучения особенностей angularjs.

Предполагая, что вам действительно нужно загрузить данные среды перед загрузкой приложения, вы можете использовать угловые инструменты для загрузки среды, а затем объявить value или constant сохранить настройки среды до загрузки приложения.

Итак, вместо использования ng-app чтобы запустить приложение, вы должны использовать angular.bootstrap загрузить его вручную.

Наблюдения: вы не должны использовать ng-app после того, как вы загрузите приложение вручную, в противном случае ваше приложение будет загружаться с угловой системой по умолчанию без учета загрузки вашей среды. Также обязательно загрузите ваше приложение после объявления всех компонентов модуля; т.е. объявлять все контроллеры, сервисы, директивы и т. д., тогда вы вызываете angular.bootstrap

Приведенный ниже код реализует решение, описанное ранее:

(function() {
    var App = angular.module("myApp", []);

    // it will return a promisse of the $http request
    function loadEnvironment () {
        // loading angular injector to retrieve the $http service
        var ngInjector = angular.injector(["ng"]);
        var $http = ngInjector.get("$http");

        return $http.get("/environment-x.json").then(function(response) {
            // it could be a value as well
            App.constant("environment ", response.data);
        }, function(err) {
            console.error("Error loading the application environment.", err)
        });
    }

    // manually bootstrap the angularjs app in the root document
    function bootstrapApplication() {
        angular.element(document).ready(function() {
            angular.bootstrap(document, ["myApp"]);
        });
    }

    // load the environment and declare it to the app
    // so then bootstraps the app starting the application
    loadEnvironment().then(bootstrapApplication);
}());
Другие вопросы по тегам