javascript 使用 $http.get 调用响应初始化 AngularJS 常量

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26803142/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 06:31:39  来源:igfitidea点击:

Initialize AngularJS Constant using $http.get call response

javascriptangularjs

提问by Kumar Sambhav

How can I initialize my angularjs app contant with reponse of a GET request.

如何通过响应 GET 请求来初始化我的 angularjs 应用程序。

For example :-

例如 :-

    angular.module('A',[]);
    angular.module('A').run( function ($rootScope,$http){
      $rootScope.safeApply = function (fn) {

                $http.get('url').success(function(result){

                    // This doesn't work. I am not able to inject 'theConstant' elsewhere in my application
                    angular.module('A').constant('theConstant', result);
                });                   
                var phase = $rootScope.$$phase;
                if (phase === '$apply' || phase === '$digest') {
                    if (fn && (typeof (fn) === 'function')) {
                        fn();
                    }
                } else {
                    this.$apply(fn);
                }
            };
      });

I want to set the constant while my app get initialized and be able to share the constant across my components.

我想在我的应用程序初始化时设置常量,并能够在我的组件之间共享常量。

What's is the best approach to accomplish this?

实现这一目标的最佳方法是什么?

采纳答案by Tibos

The result of $http.getisn't available while the app is initialized. It is only available when the server delivers it. For this reason simply keeping that value in a module constant is impossible. You run the risk of

$http.get应用程序初始化时,结果不可用。仅在服务器交付时可用。出于这个原因,简单地将该值保存在模块中是不可能的。你冒着风险

What you can do however, is wrap the call to $http.getin a service and inject that service wherever you want the constant. (Note that services can't be injected in config blocks.)

但是,您可以做的是将调用包装$http.get在一个服务中,并在您需要常量的任何地方注入该服务。(请注意,不能在配置块中注入服务。)

// grab the "constant"
angular.module('A').factory('almostConstant', function () {
  return $http.get('url').then(function(response) {
    return response.data;
  });
});

// use the "constant"
angular.module('A').controller('controller', function($scope, almostConstant) {
  almostConstant.then(function(data){
    $scope.almostConstant = data;
  });  
});

The slightly awkward mode to access the value of your almostConstant is due to its asynchronous nature. It simply is available at an unspecified time so trying to access it in a synchronous manner can introduce a lot of subtle timing bugs.

访问你的almostConstant 值的有点尴尬的模式是由于它的异步性质。它只是在未指定的时间可用,因此尝试以同步方式访问它可能会引入许多微妙的计时错误。



A very non angular-ish way of doing this would be to write your constant in the JS file directly. At the moment your server can answer to a request to 'url'with a value. Instead, you could make it answer to a request to 'url.js'with the following string:

一种非常非角度的方法是直接在 JS 文件中写入常量。目前你的服务器可以'url'用一个值来响应一个请求。相反,您可以'url.js'使用以下字符串使其响应请求:

angular.module('A').constant('theConstant', result);

where result is obviously your constant. For example if you were using php on the backend it could look something like this:

结果显然是你的常数。例如,如果您在后端使用 php,它可能如下所示:

<?php
   header('Content-Type: application/javascript');
   $constant = retrieveMyConstant();
?>
angular.module('A').constant('theConstant', <?php echo $constant; ?>);

Make sure that the constant actually looks like a JavaScript value. If it's a string, wrap it in ', if it's a JSON object write its serialization, etc.

确保常量实际上看起来像一个 JavaScript 值。如果是字符串,'则将其包装在 中,如果是 JSON 对象,则写入其序列化等。

After this you simply include a script tag pointing to url.jsin your index.htmlfile.

在此之后,您只需url.jsindex.html文件中包含一个指向的脚本标记。

Note that this solution is synchronous, so if retrieving the constant on the server takes a while, it will affect your page load time.

请注意,此解决方案是同步的,因此如果在服务器上检索常量需要一段时间,则会影响您的页面加载时间。

回答by Beno?t Guérout

As explained in this blog post, you can init a constant before bootstrapping your app:

正如这篇博文中所述,您可以在引导应用程序之前初始化一个常量:

(function() {
    var app = angular.module("A", []);

    var initInjector = angular.injector(["ng"]);
    var $http = initInjector.get("$http");

    return $http.get("/path/to/data.json")
        .then(function(response) {
            app.constant("myData", response.data);
        })
        .then(function bootstrapApplication() {
            angular.element(document).ready(function() {
                angular.bootstrap(document, ["A"]);
            });
        });


}());

回答by Kumar Sambhav

I figured out that using 'resolve' properties either in standard angular router or while using UI-Router is a better way to initialize your app.

我发现在标准角度路由器中或在使用 UI-Router 时使用“解析”属性是初始化应用程序的更好方法。

This is how did while using UI-Router:-

这是使用 UI-Router 时的做法:-

  1. Define a top level abstract state with empty inline template like this:-
  1. 使用空内联模板定义顶级抽象状态,如下所示:-
$stateProvider.state('root',{
  abstract:true,
  template:'<ui-view/>',
  resolve : {
      securityContext : function($http){
          return $http.get("/security/context");
      }
  }
});
});
$stateProvider.state('root',{
  abstract:true,
  template:'<ui-view/>',
  resolve : {
      securityContext : function($http){
          return $http.get("/security/context");
      }
  }
});
});

The property to be resolved are something that are required through out you application. Like - security token, currently logged in user etc.

要解析的属性是整个应用程序所需的内容。像 - 安全令牌,当前登录的用户等。

  1. Define child state inheriting from above state. Each and every part of you application must be managed by a state.
  1. 定义从上面的状态继承的子状态。应用程序的每个部分都必须由状态管理。
$stateProvider.state('root.optosoft.home',{
  url:'/home',
  templateUrl : '/assets/home-module/partial/home/home.html',
  controller: 'HomeCtrl',
  resolve : {
       accounts : function(securityContext){
            // Child state wil first wait for securityContext to get resolved first
      }
  }
});
$stateProvider.state('root.optosoft.home',{
  url:'/home',
  templateUrl : '/assets/home-module/partial/home/home.html',
  controller: 'HomeCtrl',
  resolve : {
       accounts : function(securityContext){
            // Child state wil first wait for securityContext to get resolved first
      }
  }
});