Dans mon application Angular
, je gère les routes/états via ui-router
. Si tout fonctionne - c'est super. Mais qu'est-ce qu'un bon moyen de gérer les erreurs survenant à l'intérieur des fonctions resolve
?
Ma solution actuelle: j'ai un état error
dédié (similaire au 404.html
Commun). Qui ressemble à ceci:
// inside config()
.state('error', {
url: '/error',
controller: 'ErrorCtrl',
templateUrl: 'error.html' // displays an error message
})
Si une erreur se produit à l'intérieur de resolve
, je l'attrape via la fonction $stateChangeError
Diffusée dans m run
:
angular.module('myModule').run(function($state) {
$rootScope.$on('$stateChangeError', function(event, toState, toParams, fromState, fromParams, error) {
event.preventDefault();
$state.go('error');
});
});
Cela fonctionne, mais Je veux changer mon message d'erreur dans mon 'error.html'
En fonction de l'erreur. Je ne veux pas polluer le $rootScope
Et je veux le faire de manière esk ui-router
.
Ma solution actuelle utilise $stateParams
Pour les données d'erreur dans mon état error
, mais je dois utiliser les paramètres de requête JSONified pour cela et obtenir une URL très moche:
// 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
});
});
Question Existe-t-il une manière différente de passer l'objet error
à mon état error
sans uglifier mon URL? (Remarque: mon objet error
est complexe et pas seulement une simple chaîne.)
Vous pouvez transmettre des données via un service auquel vous devez accéder dans votre contrôleur d'erreurs ou dans la méthode d'état d'erreur onEnter.
Ou vous pouvez "enrichir" votre état d'erreur. Peut-être que ce n'est PAS la manière angular, mais ce que je veux dire est:
$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');
});
Et dans votre configuration d'état d'erreur:
.state('error', {
url: 'error',
resolve: {
errorObj: [function () {
return this.self.error;
}]
},
controller: 'ErrorCtrl',
templateUrl: 'error.html' // displays an error message
});
J'espère que cela t'aides
Une stratégie qui a fonctionné pour moi est que les fonctions resolve
renvoient une promesse rejetée avec objet d'erreur:
$stateProvider.state('needs_authentication', {
url: '/auth',
resolve: {
user: function ($q, authService) {
if (authService.isAuthenticated()) {
...
}
else {
var errorObject = { code: 'NOT_AUTHENTICATED' };
return $q.reject(errorObject);
}
}
}
});
Cela permet à votre $stateChangeError
la fonction peut gérer des conditions d'erreur spécifiques:
$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');
}
});
Vous pouvez supprimer toute l'option url: et la remplacer par juste une option params :.
.state('error', { abstract: false, templateUrl: templateFor('error'), controller: controllerFor('error'), params: { 'error': 'An error has occurred' }, resolve: { error: [ '$stateParams', function ($stateParams) { return $stateParams.error; } ] } })
Maintenant, il n'y a pas d'URL laide. et le contrôleur peut obtenir l'erreur en tant que paramètre.