在 resolve() 引发错误后重定向到模板时出现 Angular UI Router 问题

所以我花了很长时间才理解这个问题并找到 mcve.情况如下:当用户未通过身份验证时,我试图将用户重定向到登录页面(这是非常基本的).这是代码:

So It took me a very long time to understand this issue and get to a mcve. Here is the case : I'm trying to redirect a user to a login page when he's not authenticated (this is very basic). Here is the code :

HTML:

<html>
<head>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.6/angular.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.13/angular-ui-router.min.js"></script>
    <script src="js/app.js"></script>
</head>
<body ng-app="starter">

<div ui-view></div>

<script id="login.html" type="text/ng-template">
    l
</script>

<script id="welcome.html" type="text/ng-template">
    w
</script>
</body>
</html>

JS:

    angular.module('starter', ['ui.router'])

.run(["$rootScope", "$state", function($rootScope, $state) {
    $rootScope.$on("$stateChangeError", function(event, toState, toParams, fromState, fromParams, error) {
        if (error === "nope") {
            $state.go("login");
        }
    });
}])

.config(function($stateProvider, $urlRouterProvider) {
    $urlRouterProvider.otherwise('/welcome');

    $stateProvider
        .state('welcome', {
            url: '/welcome',
            templateUrl: 'welcome.html',
            resolve: {
                "auth": ["$q", function($q) {
                    return $q.reject("nope");
                }]
            }
        })

        .state('login', {
            url: '/login',
            templateUrl: 'views/login.html'
        })
});

views/login.html"只包含vl"以查看它在屏幕上的显示.所以,当上面的代码运行时,输出是好的,但是看看 Chrome 控制台:

The "views/login.html" contains just "vl" to see it showing on the screen. So, when the above code is ran, the output is good, but look at the Chrome console :

现在,最疯狂的部分是,如果你修改 JS 并替换

Now, the crazy part of it, is if you modify the JS and replace

templateUrl: 'views/login.html'

简单的进入登录状态

templateUrl: 'login.html'

使用 html 中定义的 ng-template,一切都好!那么好吧,我想使用文件作为模板必须触发一些观察者或其他什么......好吧,不,我只是没有想法.

using the ng-template defined in the html, ALL IS GOOD ! So well, I guess using a file as template must trigger some watcher or whatever... Well no, I'm just out of ideas.

感谢您的帮助!

这里有两件事可以提供帮助:

here are two things that could help :

  • 使用 ngRoute 代替 UI Router 没有错误
  • 用 1.2.25 替换 Angular 版本没有错误

所以我认为这是 UI Router 和 Angular 1.3 的错误.但是完全不知道该怎么解决.

So I think it's a bug with UI Router and Angular 1.3. But don't know at all what to do to solve it.

推荐答案

你需要在调用 $state.go() 之前调用 event.preventDefault().

You need to call event.preventDefault() before you call $state.go().

见此处:http://plnkr.co/edit/eUosIpdN7adJFxfDo3kV?p=preview

正如您已经确定的,发生此错误的主要原因是模板 url 'views/login.html' 不存在.您说,当您将模板 url 从 'views/login.html' 更改为 'login.html' 时,一切正常,这是有道理的,因为该模板确实存在.

The main reason this error is occuring, as you have already identified, is that the template url 'views/login.html' doesn't exsit. You said that when you changed the template url from 'views/login.html' to 'login.html' everything worked, and this makes sense because that template does exist.

您看到无限摘要错误的原因是每次您尝试访问 welcome 状态时,auth 解析器都会抛出一个触发 的错误$stateChangeError 事件,就像您期望的那样.一切都很好,直到它尝试进入 login 状态.尝试转换到 login 状态失败,因为模板 url 'views/login.html' 不存在,并且此失败导致您的 otherwise 重定向将您带回 welcome 状态.此时你可以看到回到welcome状态会重新开始整个循环并导致无限摘要循环.

The reason you are seeing the infinite digest error is that each time you try to access the welcome state the auth resolver is throwing an error which triggers the $stateChangeError event like you would expect it too. Everything is fine up until the point when it tries to go to the login state. Attempting to transition to the login state fails because the template url 'views/login.html' doesn't exist, and this failure is causing your otherwise redirect to bring you back to the welcome state. You can see at this point that arriving back at the welcome state will restart the whole cycle and cause the infinite digest loop.

只要确保您的模板网址正确就可以防止这种情况发生,正如您已经发现的那样.

Simply ensuring that your template urls are correct should prevent this from happening, as you have already discovered.

相关文章