在 Angular 中,有没有办法在实例化任何控制器或指令之前但在引导应用程序之后执行一些初始逻辑?

In Angular, Is there a way to do some initial logic before any controller or directive is instantiated but after the app is bootstrapped?

我正在使用 Restangular 和 ui-router 开发一个 Angular 单页应用程序。现在我遇到了一个问题,我需要调用一些初始服务器 api 以在任何指令或控制器被实例化之前以及在 angular 被引导(angular.bootstrap)之后获取一些全局数据。我的应用程序是通过调用 angular.bootstrap 而不是使用 ng-app 指令手动引导的。


更新: 感谢@alp 和@radim-köhler。

我已经尝试了'resolve'和'运行'方法,但似乎他们可以解决我的问题。我已经用下面的代码试过了。我的要求是'hello-world'指令和'HomeCtrl'都可以被阻塞或延迟实例化,直到resolve1或resolve2被解析,但现在测试结果是:

  1. 仅在 $stateProvider.state 的解析对象中指定的 resolve2 可以阻止 HomeCtrl 的实例化,hello-world 指令是 仍然在解析 resolve2 之前被实例化。
  2. 决心1 在模块的 'run' 方法中可以 NOT 阻止它们中的任何一个(HomeCtrl 控制器 或 hello-world 指令)。

我也在Plunker

中创建了这个

也许我需要将 hello-wrold 指令和 HomeCtrl 包装到另一个控制器中,并为该控制器声明一个抽象或正常状态,对吗?

angular.module('app', ['restangular', 'ui.router'])
  .directive('helloWorld', function() {
    console.log('Initialize hello-world directive.');
    return {
      restrict: 'E',
      scope: {
        name: '@'
      },
      template: '<span>Hello <strong>{{name}}</strong></span>'
    }
  })
  .controller('HomeCtrl', function($scope) {
    console.log('Initialize home page.');
    $scope.content = 'This is in HomeCtrl';
  })
  .config(function($stateProvider, $urlRouterProvider) {
    $stateProvider.state('home', {
      url: '/',
      controller: 'HomeCtrl',
      template: '<div class="body">{{content}}</div>',
      resolve: {
        init: function($q) {
          return $q(function(resolve, reject) {
            setTimeout(function() {
              console.log('Resolving2 ...'); // resolve2
              resolve();
            }, 1000 * 3);
          });
        }
      }
    });
    $urlRouterProvider.otherwise('/');
  })
  .run(function(Restangular, $q) {
    console.log('App module is starting...');
    //console.log(Restangular, $q);
    return $q(function(resolve, reject) {
      setTimeout(function() {
        console.log('Resolving1 ...'); // resolve1
        resolve();
      }, 1000 * 5);
    });
  });

angular.element(document).ready(function() {
  angular.bootstrap(document, ['app']);
});
.body {
  margin-top: 10px;
}
<!DOCTYPE html>
<html>

<head>
  <script src="//code.angularjs.org/1.3.10/angular.js"></script>
  <script src="//rawgit.com/angular-ui/ui-router/0.2.13/release/angular-ui-router.js"></script>
  <script src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/2.4.1/lodash.min.js"></script>
  <script src="//cdnjs.cloudflare.com/ajax/libs/restangular/1.4.0/restangular.min.js"></script>
  <link rel="stylesheet" href="style.css" />
  <script src="script.js"></script>
</head>

<body>
  <hello-world name="World"></hello-world>
  <div ui-view=""></div>
</body>

</html>

控制台输出为:

App module is starting...
Initialize hello-world directive.
Resolving2 ...
Initialize home page.
Resolving1 ...

您应该检查状态定义的 resolve 设置。那将是任何东西的最佳位置,需要在

时执行
  • 应用配置后
  • 控制器创建之前

(文档中的一些引用和片段:)

Resolve

You can use resolve to provide your controller with content or data that is custom to the state. resolve is an optional map of dependencies which should be injected into the controller.

If any of these dependencies are promises, they will be resolved and converted to a value before the controller is instantiated and the $stateChangeSuccess event is fired.

...

Examples:

Each of the objects in resolve below must be resolved (via deferred.resolve() if they are a promise) before the controller is instantiated. Notice how each resolve object is injected as a parameter into the controller.

$stateProvider.state('myState', {
    resolve:{

       // Example using function with simple return value.
       // Since it's not a promise, it resolves immediately.
       simpleObj:  function(){
          return {value: 'simple!'};
       },
       ...

您可以使用 angular.Module.run 来解决这个问题。

示例:

var app = angular.module('myApp', ...);
app.run(function() {
    // your code
})

使用ui-router

建立超级状态
$stateProvider.state('app', {
    url: '',
    abstract:true,
    resolve: {
            init: function($q) {
                return $q(function(resolve, reject) {
                    setTimeout(function() {
                        console.log('Resolving ...'); // resolve
                        resolve();
                    }, 1000 * 3);
                });
            }
        },
    template: '<hello-world name="World"></hello-world><div ui-view=""></div>',


    })
     .state('app.home', {
        url: '/',
        controller: 'HomeCtrl',
        template: '<div class="body">{{content}}</div>',

    });

http://plnkr.co/edit/fUnZ2X7TFBzaRno7GSiq?p=preview

按照您的预期顺序:

Resolving ...
Initialize hello-world directive.
Initialize home page.