仅在AngularJS中完成初始化后运行控制器

Sla*_* II 14 javascript initialization angularjs

我在AngularJS应用程序中执行任何控制器之前需要加载一些全局数据(即在AngularJS中全局解析依赖关系).

例如,我有一个UserServicegetCurrentUser()它不以获取有关当前验证的用户数据到后端服务器的请求方法.我有一个控制器需要这些数据才能启动另一个请求(例如加载用户的余额).

我怎样才能做到这一点?

Sla*_* II 22

更新

如果可能,请考虑使用" 使用服务器端数据异步引导AngularJS应用程序 "一文中指定的方法.

您现在可以使用angular-deferred-bootstrap模块来实现这一目标!


我不再确定此答案的有效性,您仍然可以使用这些想法,但请务必使用您的实际代码对其进行正确测试.我将尽力保持这个答案是最新的,而不是技术.

老答案

有几种方法可以解决异步应用程序初始化问题.

当涉及到一个控制器调用之前必须解决数据-你可以很容易地使用resolve的选项ngRoute$routeProvider.但是,当您需要在调用任何控制器之前加载某些全局数据时 - 您必须即兴创作.

我试图在这个答案中收集所有可能的解决方案.我按优先顺序提供它们.

1.使用ui-router

使用ui-router而不是native时ngRoute,可以在激活子状态之前创建抽象根状态并解析其中的所有数据.

我建议使用这种方法.ui-router提供了许多其他功能,包括分层次地解析依赖项的能力,并且被开发人员社区广泛接受.

module.config(function($urlRouterProvider, stateHelperProvider) {
    $urlRouterProvider.otherwise('/404');
    stateHelperProvider.setNestedState({
        name: 'root',
        template: '<ui-view/>',
        abstract: true,
        resolve: {
            user: function(UserService) {
                // getCurrentUser() returns promise that will be resolved
                // by ui-router before nested states are activated.
                return UserService.getCurrentUser();
            }
        },
        children: [{
            name: 'index',
            url: '/',
            templateUrl: '/partials/index'
        }, {
            name: 'not-found',
            url: '/404',
            templateUrl: '/partials/404'
        }, {
            name: 'balance',
            url: '/balance',
            templateUrl: '/partials/balance',
            resolve: {
                balance: function(UserService, user) {
                    // Using data resolved in parent state.
                    return UserService.getBalanceByAccountId(user.accountId);
                }
            }
        }]
    });
});
Run Code Online (Sandbox Code Playgroud)

stateHelper在使用抽象根范围方法时,这将有助于减少代码.

根作用域定义为抽象,因此无法直接激活且没有URL.

template: '<ui-view/>' 是嵌套视图正确呈现所必需的.

2.在根控制器中做出承诺

您可以制作promises并将它们添加到$rootScope根控制器的内部,即run()功能.

我创建了一个Plunk来演示这个想法:http://plnkr.co/edit/gpguG5Y2S4KOz1KOKzXe?p = preview

这是一个完美的解决方案,然而,它使代码膨胀并使其更难以使用和理解(回调地狱).只有当第一种方法不适合你时,我才会推荐它.

3.使用应用程序页面传递数据

您可以将所有初始化数据直接包含在服务器上生成的HTML页面中,并从您的应用程序访问它.

考虑这个例子:

<html>

<body>

    <script src="application.js"></script>
    <script type="text/javascript">
        application.init({
            // Pass your data here.
            userData: { ... }
        });
    </script>

</body>

</html>
Run Code Online (Sandbox Code Playgroud)

您可以在init()自定义application对象的方法中手动引导AngularJS应用程序.

我不太喜欢这种方法,因为我确实认为Web应用程序的前端和后端应该高度分离.理想情况下,您的前端应该是一个静态网站(例如,可以通过CDN提供的一堆HTML,CSS和JS),您的后端应该是一个没有表示层的严格的API服务器(即它应该对HTML,CSS和这样).但是,如果您能够在应用程序组件之间实现紧密集成,那么它就是一个可行的解决方案