Angular: 在 config/run 之前加载环境属性

Angular: load environment properties before config/run

我正在开发一个 angular 应用程序,这个应用程序有大约 10 个可配置属性(取决于环境和客户端)。

我在 json 配置文件中有这些属性,但这真的很麻烦:每个 env/company 必须有特定的构建。所以我想在应用程序加载时从后端检索一次这些属性。

因此,为了做到这一点,我创建了一个 Provider

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 调用以填充其环境变量的 Provider?

提前致谢!

这是探索 angularjs 功能的绝佳方案。

假设你确实需要在app加载之前加载环境数据,你可以使用angular工具加载环境然后声明一个value或者一个constant来存储您在应用 bootstraps.

之前的环境配置

因此,您必须手动使用 angular.bootstrap 到 bootstrap,而不是使用 ng-app 来启动您的应用程序。

Observations: You mustn't use ng-app once you are bootstrapping the app manually, otherwise your app will load with the angular default system without respecting your environment loading. Also, make sure to bootstrap your application after declare all module components; i.e. declare all controllers, servieces, directives, etc. so then, you call 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);
}());