一尘不染

将$ state(ui-router)注入$ http拦截器会导致循环依赖

angularjs

我正在努力实现的目标

如果$ http请求返回401错误,我想过渡到某个状态(登录)。因此,我创建了一个$ http拦截器。

问题

当我试图将’$ state’插入拦截器时,我得到了循环依赖。为什么以及如何解决?

//Inside Config function

    var interceptor = ['$location', '$q', '$state', function($location, $q, $state) {
        function success(response) {
            return response;
        }

        function error(response) {

            if(response.status === 401) {
                $state.transitionTo('public.login');
                return $q.reject(response);
            }
            else {
                return $q.reject(response);
            }
        }

        return function(promise) {
            return promise.then(success, error);
        }
    }];

    $httpProvider.responseInterceptors.push(interceptor);

阅读 240

收藏
2020-07-04

共1个答案

一尘不染

修复

使用$injector服务获取对服务的引用$state

var interceptor = ['$location', '$q', '$injector', function($location, $q, $injector) {
    function success(response) {
        return response;
    }

    function error(response) {

        if(response.status === 401) {
            $injector.get('$state').transitionTo('public.login');
            return $q.reject(response);
        }
        else {
            return $q.reject(response);
        }
    }

    return function(promise) {
        return promise.then(success, error);
    }
}];

$httpProvider.responseInterceptors.push(interceptor);

原因

angular-ui-router$http服务作为依赖项注入$TemplateFactory,然后在分派拦截器时在其$http内部创建对$httpProvider自身的循环引用。

如果您尝试将$http服务直接注入拦截器中,则将抛出相同的循环依赖异常。

var interceptor = ['$location', '$q', '$http', function($location, $q, $http) {

关注点分离

循环依赖项异常可能表明您的应用程序中存在混合的关注点,这可能会导致稳定性问题。如果发现自己有这种例外情况,则应该花些时间查看自己的体系结构,以确保避免最终导致引用自己的任何依赖项。

@斯蒂芬·弗里德里希的答案

我同意以下答案,即使$injector用来直接获得所需服务的引用不是理想的选择,可以将其视为反模式。

发出事件是一种更为优雅且脱钩的解决方案。

2020-07-04