У меня одностраничное приложение AngularJS, состоящее из нескольких модулей, целью которых является предоставление пользователю совместной панели (основного виджета) и других связанных с ними виджетов (других подключенных пользователей, метаданных пэдов и т. Д.).В AngularJS, как запустить код после инициализации всех контроллеров?
Я решил разделить приложение следующим образом:
- 1 Модуль хостинга службы, ответственный за обнажая методы инициализации для компонента колодки
- N модулей хостинга пользовательских директив (и их контроллер), соответствующей различные виджеты в приложении
- 1 модуль, отвечающий за параметры сбора и инициализации компонента подушки
Давайте си mplify this, предположив, что у меня есть только 1 виджет, единственной целью которого является отображение пользователю статуса сообщения: «аутентификация», «аутентификация», «ошибка» или «готовность».
Я решил использовать шаблон подписки/уведомления с услугой, чтобы позволить виджету получать уведомление об изменении состояния общего компонента.
Услуга:
angular.module("app.core").factory("padService", padService);
function padService() {
// Callback registration and notification code omitted
return {
initialize: function (authToken) { ... },
onAuthenticated: function (callback) { ... },
onReady: function (callback) { ... },
onError: function (callback) { ... }
};
}
Виджет:
angular.module("app.widget").directive("widget", widget);
function widget() {
return {
templateUrl: 'app/widget.html',
restrict: 'E',
controller: widgetController
};
}
function widgetController($scope, padService) {
$scope.message = "authenticating";
padService.onAuthenticated(function (user) {
$scope.message = "authenticated";
// Do other stuff related to user authentication event
});
padService.onReady(function (padInstance) {
$scope.message = "ready";
// Do other stuff related to pad readiness event
});
padService.onError(function (error) {
$scope.message = "error";
// Do other stuff related to error event
});
}
Теперь "модуль инициализатор", в своей простейшей форме, собирает аутентификации маркера authToken
из фрагмента URL (по аналогии с OAuth2) и просто вызывает padService.initialize(authToken);
. Обратите внимание, что это также может быть выделенное всплывающее окно аутентификации, поэтому оно находится в собственном модуле.
Моя проблема в том, что я не знаю, где положить этот фрагмент кода. Все места, я пытался в результате размещаются слишком рано в угловом процессе начальной загрузки и/или не обновлять виджет:
angular.module("app.initializer").run(run);
function run($document, $timeout, tokenService, padService) {
// This does not work because run() is called before the
// controllers are initialized (widget does not get notified)
var authToken = tokenService.getTokenFromUrl();
padService.initialize(authToken);
$document.ready(function() {
// This does not work because angular does not detect
// changes made to the widget controller's $scope
var authToken = tokenService.getTokenFromUrl();
padService.initialize(authToken);
// This does not work in firefox for some reason (but
// does in chrome!)... except if I enter debug mode or
// set the timeout to a longer value, which makes it
// either really difficult to diagnostic or ugly as hell
$timeout(function() {
var authToken = tokenService.getTokenFromUrl();
padService.initialize(authToken);
}, 0);
});
}
Имеет ли сервис знания о том, какие контроллеры будут подписываться на свои услуги? Или это имеет значение? Что служба должна знать от своих клиентов, чтобы функционировать? – georgeawg
Вы можете посмотреть, как ui-riouter реализует свой метод 'resolve' https://github.com/angular-ui/ui-router/blob/master/src/resolve.js –
Служба не знает своих подписчиков, она просто вызывает внутренний метод 'notify()', когда происходит событие, которое, в свою очередь, вызывает каждый зарегистрированный обратный вызов с некоторыми аргументами (на самом деле это просто пользовательская реализация '$ on 'и' $ broadcast', чтобы избежать загрязнения глобальных имен событий). Службе не нужно ничего знать о функциях своих подписчиков, но ее необходимо инициализировать с помощью набора параметров (здесь токен аутентификации, предоставляемый модулем 'app.initializer'). –