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

Ошибка обработки в функции разрешения 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 является сложным, а не просто простой строкой.)

4b9b3361

Ответ 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. и контроллер может получить ошибку в качестве параметра.