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

时间:2015-01-24 15:21:30

标签: javascript angularjs angular-ui-router restangular

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


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

我尝试了“解析”和“运行”方法,但似乎其中任何一个都可以解决我的问题。我用以下代码尝试过它们。我的要求是'hello-world'指令和'HomeCtrl'可以被阻止或延迟实例化,直到resolve1或resolve2被解决,但现在测试结果是:

  1. $ stateProvider.state中仅在解析对象中指定的resolve2 可以阻止HomeCtrl的实例化,hello-world指令是 仍然在解析resolve2之前实例化。
  2. resolve1 在模块的'run'方法中, NOT 可以阻止它们中的任何一个(HomeCtrl控制器 或hello-world指令)。
  3. 我也在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模块正在启动...
      初始化hello-world指令。
      解决2 ...
      初始化主页。
      解决1 ...

3 个答案:

答案 0 :(得分:3)

您可以使用angular.Module.run

示例:

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

答案 1 :(得分:2)

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

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

(来自doc的一些引用和摘录:)

Resolve

  

您可以使用resolve为控制器提供自定义状态的内容或数据。 resolve是一个可选的依赖关系图,应该注入控制器。

     

如果这些依赖项中的任何一个是promise,它们将在实例化控制器并触发$ stateChangeSuccess事件之前被解析并转换为值。

...

  

示例:

     

在实例化控制器之前,必须解析下面解决的每个对象(如果它们是承诺,则通过deferred.resolve())。注意每个解析对象如何作为参数注入控制器。

$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!'};
       },
       ...

答案 2 :(得分:2)

使用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.