处理ui-routers解决功能错误? (又名$ stateChangeError)将数据传递给错误状态?

时间:2014-04-08 12:21:53

标签: javascript angularjs angular-ui-router

在我的Angular应用程序中,我通过ui-router处理路由/状态。如果一切正常 - 它很棒。但是什么是良好的方法来处理resolve函数内发生的错误?

我目前的解决方案: 我有一个专用的error州(类似于公共404.html)。看起来像这样:

// inside config()
.state('error', {
  url: '/error',
  controller: 'ErrorCtrl',
  templateUrl: 'error.html' // displays an error message
})

如果resolve内发生错误,我会通过m $stateChangeError函数中的广播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&#es;方式进行污染。

我当前的解决方案使用$stateParams将错误数据导入我的error状态,但我必须使用JSONified查询参数来获取一个非常难看的网址:

// 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状态,而无需更新我的网址? (注意:我的error对象很复杂,而不仅仅是一个简单的字符串。)

3 个答案:

答案 0 :(得分:25)

您可以通过服务传递数据,您应该在错误控制器或onEnter错误状态方法中访问该数据。

或者你可以"丰富"你的错误状态。也许它不是有角度的方式,但我的意思是:

$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
});

希望这有帮助

答案 1 :(得分:25)

对我有用的策略是让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');
    }
});

答案 2 :(得分:4)

您可以删除整个网址:选项并将其替换为只有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;
                            }
                        ]
                    }
                })

现在没有丑陋的网址。并且控制器可以将错误作为参数。