【问题标题】:Is there a way to prevent the initial state from loading when my angularjs app starts up?有没有办法阻止我的 angularjs 应用程序启动时加载初始状态?
【发布时间】:2014-08-24 18:28:44
【问题描述】:

背景

在加载第一个状态之前,我的应用需要向服务器发出请求以验证用户是否具有经过身份验证的会话。根据 url,用户可能需要被重定向到登录页面。

即如果初始 url 是 myapp.com/#/profile 并且用户没有预先存在的经过身份验证的会话,他们将被重定向到 myapp.com/#/login


问题

我有处理这种情况的逻辑,但是在向服务器发出会话数据请求之后,在它完成之前,会在服务器响应之前触发初始状态更改并加载和显示页面


可能的解决方案

1) 我使用 django 作为后端,因此可以从应用程序中删除初始服务器请求,并将数据直接传递给 django 模板中的应用程序。要么通过

  • 主控制器的 ng-init - 虽然我读过这是一个 坏主意,因为这不是它的预期用途

  • 或者在 django 模板中的脚本标签中 - 我讨厌 这样做,因为我宁愿将所有应用程序逻辑单独保存在 js 文件中

2) 监听初始 $stateChangeStart,取消它,然后在服务器请求完成后调用 $state.reload()


问题

在我看来,在初始状态更改发生之前满足某些标准是一个相当普遍的要求,所以我想知道我是否遗漏了文档中的某些内容,并且已经有一种内置的方法来处理这种情况?

或者有没有办法停用 $urlRouterProvider/$stateProvider 以防止发生初始状态更改?

【问题讨论】:

  • 根据您在 Angular 中进行路由的方式,使用 resolve 属性进行路由:docs.angularjs.org/api/ngRoute/provider/$routeProvider - 我将其用于您正在谈论的内容。在resolve 回调中,我向我的服务器发出AJAX 请求以从会话中获取用户信息。如果没有返回任何内容,则表示它们未通过身份验证,我拒绝 resolve 中使用的承诺
  • 谢谢@Ian。我考虑过这一点,但这是否意味着必须向每个州的解析属性添加相同的功能?
  • 我不确定我是否跟随,但我认为是的。您可以声明该函数一次,然后将其用于所有路由(传递引用) - 这有什么问题?
  • 我想没什么。如果有一种方法可以为 routeProvider 本身添加一个通用解析(它会被所有路由调用),而不是必须将它添加到配置中的每个路由,它看起来会更干净。然后也许还有一种方法可以在不再需要它时将其删除。
  • 我很想听听其他人的解决方案,因为当我需要这样的解决方案时,我可以在广泛的搜索中找到使用resolve 的全部内容。似乎任何形式的状态变化(或其他)监听都不允许您“恢复”或“取消”(仅“取消”)。

标签: javascript django angularjs angular-ui-router


【解决方案1】:

假设您的所有身份验证逻辑都已经在 AuthService 之类的内部,是否可以执行以下操作?

// 'AuthService' injected earlier
$rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) {
    if (!AuthService.isAuthenticated()) {
        // prevent navigation. don't go anywhere;
        // navigation will occur inside AuthService
        event.preventDefault();

        AuthService.setNextState(toState.name);
        AuthService.authenticateWithServer();
    }
    // proceed normally if user is already authenticated
});

那么,你的AuthService

app.service('AuthService', function($rootScope, $http, $state) {
    var next;

    this.setNextState = function(nextState) { next = nextState; };

    this.isAuthenticated = function() { ... };

    this.authenticateWithServer = function() {
        $http.post('/authen', { ... }).success(function(user){
            // house-keeping
            $rootScope.user = user;

            // navigate by state name
            $state.go(next);
        }).error(function(error) {
            // navigate to login screen
            $state.go('login');
        });
    };
});

这样,您的状态定义是干净的,并且身份验证逻辑被隔离在一个地方。您还可以确保在获得所需的所有信息之前永远不会进行导航。

【讨论】:

  • 谢谢,它帮助我想出了一个类似的解决方案。我的问题略有不同,因为有未经身份验证的用户可以访问的状态
  • @james 如果有帮助,您应该考虑接受答案。至少在未来,人们会更倾向于点击并阅读此页面,而不是将其视为未回答的问题而忽略。
猜你喜欢
  • 1970-01-01
  • 2011-06-29
  • 2012-12-20
  • 2020-02-22
  • 1970-01-01
  • 1970-01-01
  • 2011-10-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多