$ location.path无法从http拦截器工作

wit*_*dle 6 angularjs

这是你相当直接的设置,我有一个http拦截器正在寻找401s,如果发现用户被重定向到登录页面:

function($location, $q)
{
    return {
        request: function (config) {
            return config || $q.when(config);
        },
        requestError: function(request){
            return $q.reject(request);
        },
        response: function (response) {
            return response || $q.when(response);
        },
        responseError: function (response)
        {
            if (response && response.status === 401)
            {
                $location.path('/login');                    
            }

            return $q.reject(response);
        }
    };

}
Run Code Online (Sandbox Code Playgroud)

问题是$location.path('/login')呼叫似乎不起作用,路径完全被忽略,我仍然在我的会话到期时我在路上(尽管是空白页).一种可能的解决方法是使用传统方法,window.location = '/#!/login';但我发现这不太理想.我还发现,如果我删除该return $q.reject(response);行,我得到它的工作,但这引入了另一个错误,其中无法找到响应的数据属性(此处讨论的解决方案:Angular.js $ http.post TypeError:无法读取未定义的属性'data') .

我正在跑角1.2.21.

关于可能会发生什么的任何想法?回到window.location不是世界的尽头,但我喜欢这个神秘的一个很好的整洁解决方案:).

提前致谢.

Sir*_*zha 2

我也有同样的问题。

我不确定,但看起来$location.path(...)不会更改位置,因为应用程序会等待所有承诺都得到解决,并且拦截器内的承诺被拒绝(return $q.reject(response);

在我的例子中,执行http请求的服务被放置在resolveUI路由器状态部分内,所以我可以使用$stateChangeError事件来处理错误。(对于 ngRoute 使用 $routeChangeError 事件)

希望这可以帮到你 :)

注意我的应用程序后端在 401 响应正文中返回自定义错误消息

PS 一定有更好的解决方案

更新:

更通用的解决方法:

module.config 内的拦截器

...
responseError: function (response) {
    if (response && response.status === 401) {
        $rootScope.$emit('loginRequired');
    }

    return $q.reject(response);
}
...
Run Code Online (Sandbox Code Playgroud)

和 module.run 部分中某处的事件处理程序

$rootScope.$on('loginRequired', function() {
    $location.path('/login');
});
Run Code Online (Sandbox Code Playgroud)

(我已经测试过处理程序,$state.go('login')$location.path('/login');也应该有效:))