Подтвердить что ты не робот

Контроллеры запуска только после завершения инициализации в AngularJS

У меня есть некоторые глобальные данные, которые необходимо загрузить до того, как какой-либо контроллер будет выполнен в моем приложении AngularJS (т.е. разрешить зависимости глобально в AngularJS).

Например, у меня есть UserService с методом getCurrentUser(), который выполняет запрос на серверный сервер, чтобы получить данные о пользователе, прошедшем проверку подлинности. И у меня есть контроллер, которому нужны эти данные, чтобы запустить еще один запрос (например, для загрузки пользовательского баланса).

Как я могу это достичь?

4b9b3361

Ответ 1

Update

Пожалуйста, рассмотрите возможность использования метода, указанного в Асинхронно загрузочные приложения AngularJS с данными на стороне сервера", если это возможно.

Вы можете использовать модуль angular-deferred-bootstrap, чтобы достичь этого!


Я больше не уверен в правильности ответа на этот вопрос, вы все равно можете использовать идеи, но не забудьте правильно проверить его с помощью своего фактического кода. Я постараюсь сохранить этот ответ в курсе новейших технологий.

Старый ответ

Существует несколько подходов к проблеме инициализации асинхронного приложения.

Когда дело доходит до данных, которые должны быть разрешены перед вызовом одного контроллера, вы можете легко использовать опцию resolve ngRoute $routeProvider. Однако, когда вам нужны некоторые глобальные данные для загрузки до вызова ЛЮБОГО контроллера - вам нужно импровизировать.

Я попытался собрать все возможные решения в этом ответе. Я предоставляю их в порядке предпочтения.

1. Использование ui-router

При использовании ui-router вместо native ngRoute вы можете создать абстрактное состояние root и разрешить все данные в нем, состояния активированы.

Я бы рекомендовал использовать этот подход. 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. Создание promises в корневом контроллере

Вы можете сделать promises и добавить их в $rootScope внутри вашего корневого контроллера, т.е. run().

Я создал Plunk, чтобы продемонстрировать идею: http://plnkr.co/edit/gpguG5Y2S4KOz1KOKzXe?p=preview

Это прекрасно работающее решение, однако оно раздувает код и усложняет его использование и понимание (callback hell). Я бы рекомендовал его, только если первый подход не работает для вас.

3. Передача данных с помощью страницы приложения

Вы можете включить все данные инициализации непосредственно на HTML-страницу, сгенерированную на сервере, и получить к ней доступ из вашего приложения.

Рассмотрим следующий пример:

<html>

<body>

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

</body>

</html>

И вы можете загружать приложение AngularJS вручную в методе init() вашего пользовательского объекта application.

Мне не нравится этот подход, так как я считаю, что интерфейс и бэкэнд веб-приложения должны быть сильно разделены. В идеале ваш внешний интерфейс должен быть статическим веб-сайтом (например, связкой HTML, CSS и JS, которые могут быть доставлены через CDN), и ваш сервер должен быть строго сервером API без уровня представления (то есть он ничего не должен знать о HTML, CSS и например). Однако это рабочее решение, если вы можете жить с плотной интеграцией между компонентами приложения.