为什么event.preventDefault()无法在角度js中取消$ routeChangeStart事件

时间:2014-09-19 20:23:14

标签: javascript angularjs

我在角度js应用程序中完成了路径限制。当用户已经登录时,它不应该移动到登录页面。这是我的代码:

.run(function($rootScope, $location, Auth) {
    $rootScope.$on('$routeChangeStart', function(event, next) {

       Auth.isLoggedInAsync(function(loggedIn) {

        if(loggedIn){ //when user loged in it should not move to login page
          if ($location.path() == "/participant/login"){
            event.preventDefault();
          }
        }
      });
    });

此代码不会给出任何类型的错误。但是当用户已经登录时它会移动到登录页面。我认为这里event.preventDefault()不起作用。请告诉我,如果我做错了或者如果你有什么好方法可以解决这个问题吗?

2 个答案:

答案 0 :(得分:0)

我不确定您的Auth对象(服务?)是什么,但该方法被称为异步...所以可能发生的是,Auth.isLoggedInAsync()被触发,然后外部函数继续。由于在Auth.isLoggedInAsync()之后没有任何内容,它基本上返回undefined,并且路由更改继续进行。

可能会调用event.preventDefault(),但外部函数不会等待Auth.isLoggedInAsync()解析,因此默认操作可能已经发生。没有什么可以阻止的。

考虑使用阻塞函数(同步),或者将用户状态分配给已经将其值解析的对象属性。

.run(function($rootScope, $location, Auth) {
  $rootScope.$on('$routeChangeStart', function(event, next) {
    if (Auth.userLoggedIn) { //when user loged in it should not move to login page
      if ($location.path() === "/participant/login"){
        event.preventDefault();
      }
    }
  });
});

请注意,上面的代码要求您更改Auth,因为Auth.userLoggedIn是一个属性(您可能需要定义,除非我击中靶心;)

答案 1 :(得分:0)

我不认为@ wiherek的答案通常会起作用,因为它不会保证Auth服务在调用$routeChangeStart处理程序时就已准备就绪。< / p>

你可以依赖的是,如果路由的resolve参数中的任何项目返回promises,那么:

  • 承诺将在路线更改发生之前解决,或
  • 在广播$rootScope.$routeChangeStart之前,承诺将被拒绝。

所以在你的路线定义中你可以这样:

$routeProvider.when('/participant/login', {
  resolve: {
    auth: function(Auth, $q) {
      var deferred = $q.defer();
      Auth.isLoggedInAsync(function(loggedIn) {
        if (loggedIn) {
          deferred.resolve();
        }
        else {
          deferred.reject({alreadyLoggedIn: true});
        }
      }).catch(function() {
        deferred.reject();
      });
      return deferred.promise;
    }
  }
);

你可以通过听$routeChangeError

来抓住它
app.run(function($rootScope, $location, Auth) {
  $rootScope.$on("$routeChangeError", function(event, current, previous, rejection) {
    if (rejection != null && rejection.alreadyLoggedIn) {
      // We should get here if and only if
      // `deferred.reject({alreadyLoggedIn: true})` was called from the
      // above.
    }
  });
});