Ошибка обработки в функции разрешения ui-routers? (aka $stateChangeError) Передача данных в состояние ошибки?
Внутри моего приложения Angular
я обрабатываю маршруты/состояния через ui-router
. Если все работает - это здорово. Но что является хорошим способом обработки ошибок, возникающих внутри функций resolve
?
Мое текущее решение:
У меня есть выделенное состояние error
(аналогично общему 404.html
). Что выглядит так:
// inside config()
.state('error', {
url: '/error',
controller: 'ErrorCtrl',
templateUrl: 'error.html' // displays an error message
})
Если внутри resolve
возникает ошибка, я получаю ее через переданную функцию $stateChangeError
в m run
:
angular.module('myModule').run(function($state) {
$rootScope.$on('$stateChangeError', function(event, toState, toParams, fromState, fromParams, error) {
event.preventDefault();
$state.go('error');
});
});
Это работает, , но. Я хочу изменить свое сообщение об ошибке внутри моего 'error.html'
в зависимости от ошибки. Я не хочу загрязнять $rootScope
, и я хочу сделать это с помощью ui-router
'esk.
Мое текущее решение использует $stateParams
для данных ошибки в моем состоянии error
, но для этого я должен использовать параметры запроса JSONified и получить очень уродливый URL:
// inside config()
.state('error', {
url: '/error?data&status&config', // accept these three params
controller: 'ErrorCtrl',
templateUrl: 'error.html' // displays an error message
})
angular.module('myModule').run(function($state) {
$rootScope.$on('$stateChangeError', function(event, toState, toParams, fromState, fromParams, error) {
event.preventDefault();
$state.go('error', JSON.stringify(error)); // error has data, status and config properties
});
});
Вопрос
Есть ли другой способ, как я могу передать объект error
в мое состояние error
без угасания моего URL-адреса? (Примечание. Мой объект error
является сложным, а не просто простой строкой.)
Ответы
Ответ 1
Вы можете передавать данные через службу, которую вы должны получить в своем контроллере ошибок или в режиме onEnter состояния ошибки.
Или вы можете "обогатить" свое состояние ошибки. Возможно, это НЕ путь angular, но я имею в виду:
$rootScope.$on('$stateChangeError', function (event, toState, toParams, fromState, fromParams, error) {
event.preventDefault();
$state.get('error').error = { code: 123, description: 'Exception stack trace' }
return $state.go('error');
});
И в конфигурации вашего состояния ошибки:
.state('error', {
url: 'error',
resolve: {
errorObj: [function () {
return this.self.error;
}]
},
controller: 'ErrorCtrl',
templateUrl: 'error.html' // displays an error message
});
Надеюсь, что это поможет
Ответ 2
Стратегия, которая работала для меня, заключалась в том, чтобы функции resolve
возвращали отклоненное обещание с объектом ошибки:
$stateProvider.state('needs_authentication', {
url: '/auth',
resolve: {
user: function ($q, authService) {
if (authService.isAuthenticated()) {
...
}
else {
var errorObject = { code: 'NOT_AUTHENTICATED' };
return $q.reject(errorObject);
}
}
}
});
Это позволяет вашей функции $stateChangeError
обрабатывать определенные условия ошибки:
$rootScope.$on('$stateChangeError', function (evt, toState, toParams, fromState, fromParams, error) {
if (angular.isObject(error) && angular.isString(error.code)) {
switch (error.code) {
case 'NOT_AUTHENTICATED':
// go to the login page
$state.go('login');
break;
default:
// set the error object on the error state and go there
$state.get('error').error = error;
$state.go('error');
}
}
else {
// unexpected error
$state.go('error');
}
});
Ответ 3
Вы можете удалить весь url: option и заменить его только параметром:.
.state('error', {
abstract: false,
templateUrl: templateFor('error'),
controller: controllerFor('error'),
params: { 'error': 'An error has occurred' },
resolve: {
error: [
'$stateParams', function ($stateParams) {
return $stateParams.error;
}
]
}
})
Теперь нет уродливого url. и контроллер может получить ошибку в качестве параметра.