AngularJS - отложенный запуск $stateChange

Все мы знаем и любим AngularJS (любят возможно не все). У ангуляра есть прекрасный модуль ui.router, который позволяет очень удобно подключать view в зависимости от параметров URL. А также генерировать ссылки на эти сущности с помощью директив ui-sref.

К view можно привязать контроллер, который будет инстанцироваться при каждом переходе. Это очень удобно использовать в похожих по логике элементах приложения, вместо классических переходов на детальные страницы с перезагрузкой. Контроллер при каждом переходе подключит нужные watchers, обратится к factory или services, предварительно сделав destructor объекта прошлого элемента.

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

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

'use strict';

app.service('DelayService', function ($rootScope, $q, $state, $log) {
	$log.debug('DelayService instance');

	/** 
	* создаем переменную объекта перехода в rootScope, чтобы была 
	* доступна из любого контроллера или сервиса.
	*/
	$rootScope.delayObj = null;

	/** 
	* подписываемся на событие смены $state в ui.route
	*/
	$rootScope.$on('$stateChangeStart',
		function(event, toState, toParams, fromState, fromParams) {
			/** 
			* Если переменная объекта не определена
			*/
			if($rootScope.delayObj === null) {

				/** Запускаем создание в переменной deffered объекта*/	
				EffectService.makeObjCallback();
				
				/** 
				*	Вешаем на его выполнение "принудительный" переход
				* 	на нужный state c нужными параметрами
				*/
				EffectService.getPromise().then(function () {
					$state.go(toState.name, {
						id : toParams.id
					});

					/** обнуляем defferd */
					$rootScope.effectObj = null;
				});

				/** Блокируем "нативное" ui.route переключение */
				event.preventDefault();
			}
		});

	/**
	*	Собственно сам сервис, которые состоит из 2 простых функций 
	*/
	var DelayService ={
		/** Создание deffered объекта */
		makeObjCallback: function() {
			$rootScope.delayObj = $q.defer();
		},

		/** Return ссылки на него для resolve() */ 
		getPromise: function() {
			return $rootScope.delayObj.promise;
		}
	};

	return DelayService;
});

Ну и, собственно, все. Теперь в любом своем контроллере(который к примеру отвечает за анимацию "ухода" или вообще любом другом) подключаете данный сервис. И остается выполнить магическую строчку:

DelayService.getPromise().resolve();

Проделав перед этим все необходимые действия.

Будем надеятся кому-нибудь это поможет в разработке своих приложений на AngularJS. Спасибо за внимание.

19 Октября 2016
Последние новости
29 Сентября 2016
Создан интернет-магазин для компании «Надеко»
29 Июля 2016
Создан сайт для компании «ACS Termal»
Сделать заказ
Нужен интернет-магазин?