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

时间:2014-11-20 22:07:12

标签: javascript angularjs initialization

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

例如,我有一个UserService,其getCurrentUser()方法向后端服务器发出请求,以获取有关当前已验证用户的数据。我有一个控制器需要这些数据才能启动另一个请求(例如加载用户的余额)。

我怎样才能做到这一点?

1 个答案:

答案 0 :(得分:22)

更新

如果可能,请考虑使用«Asynchronously Bootstrapping AngularJS Applications with Server-Side Data»文章中指定的方法。

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


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

旧答案

有几种解决异步应用程序初始化问题的方法。

说到在调用单个控制器之前必须解决的数据 - 您可以轻松使用resolve ngRoute的{​​{1}}选项。但是,当您需要在调用任何控制器之前加载某些全局数据时 - 您必须即兴发挥。

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

1。使用 ui-router

使用ui-router而不是本地$routeProvider时,您可以在激活子状态之前创建抽象根状态并解析其中的所有数据。

我建议使用这种方法。 ngRoute提供了许多其他功能,包括以层次结构方式解析依赖关系的功能,并且被开发人员社区广泛接受。

实施例

ui-router

使用抽象根范围方法时,stateHelper将极大地减少代码。

根作用域定义为摘要,因此无法直接激活且没有URL。

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); } } }] }); }); 是嵌套视图正确呈现所必需的。

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

您可以制作承诺并将其添加到根控制器内的template: '<ui-view/>',即$rootScope功能。

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

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

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

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

考虑这个例子:

run()

您可以在自定义<html> <body> <script src="application.js"></script> <script type="text/javascript"> application.init({ // Pass your data here. userData: { ... } }); </script> </body> </html> 对象的init()方法中手动引导AngularJS应用程序。

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