小编典典

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

angularjs

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

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

我该如何实现?


阅读 224

收藏
2020-07-04

共1个答案

小编典典

更新资料

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

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


我不确定该答案的有效性,您仍然可以使用这些想法,但是请确保使用实际代码对其进行适当的测试。我将尝试从不采用最新技术来使此答案保持最新。

旧答案

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

当谈到前一个控制器被称为必须解决数据-
你可以很容易地使用resolve的选项ngRoute$routeProvider。但是,如果您需要在调用ANY控制器之前加载一些全局数据,则必须即兴进行。

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

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);
                }
            }
        }]
    });
});

stateHelper使用抽象根作用域方法时,这将大大减少代码。

根范围定义为抽象,因此不能直接激活,也没有URL。

template: '<ui-view/>' 必须正确呈现嵌套视图。

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

您可以做出承诺并将其添加到$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>

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

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

2020-07-04