event.preventDefault() 在 .then 内部不工作

event.preventDefault() not working inside of .then

代码:

angular
  .module('mean-starter')
  .run(run)
;

function run($rootScope, Auth, $state) {
  function preventStateChange (message, event, redirect) {
    console.log(event);
    event.preventDefault();
    alert(message);

    if (redirect) {
      $state.go(redirect);
    }
  }

  $rootScope.$on('$stateChangeStart', function (event, toState, toParams) {
    if (typeof toState.authenticate === 'undefined') { // this route doesn't require permissions
      return;
    }

    event.preventDefault(); // WORKS HERE

    Auth
      .getCurrentUser()
      .then(function (currentUser) {
        event.preventDefault(); // DOESN'T WORK HERE
        var isLoggedIn = !!currentUser._id;
        var isAdmin = isLoggedIn && currentUser.role === 'admin';
        var isAuthorized = isLoggedIn && currentUser._id.toString() === toParams.id;

        if (toState.authenticate.loggedOut && isLoggedIn) { // this route requires you to be logged out
          preventStateChange("You're logged in.", event);
        }
        else if (!isLoggedIn) {
          preventStateChange('Must be logged in to access this route.', event, 'login');
        }
        else if (toState.authenticate.authorized && !isAuthorized && !isAdmin) {
          preventStateChange('You are not authorized to access that route.', event);
        }
        else if (toState.authenticate.isAdmin && !isAdmin) {
          debugger;
          event.preventDefault();
          preventStateChange('You must be an admin to access this route.', event);
        }
      })
    ;
  });
}

当我以非管理员身份登录并转到 localhost:3000/admin:

  1. 我收到一条警告说,"You must be an admin to access this route."
  2. 我进入管理页面,可以看到所有我不应该看到的管理内容。

这是为什么?

当我在调试器中检查时,event.preventDefault 已定义,而且它似乎被调用了。这是注销到控制台的 event 对象:

defaultPrevented 属性 设置为 true!


更新:它在 .then 之外工作,但在 .then 内部不起作用。这是令人惊讶的,因为它是在 .then.

内部定义的

更新 2:我的猜测是 event 在到达 .then 之前执行默认操作。所以本质上,.then 为时已晚。

你的第二个猜测基本正确。在所有当前事件处理程序都已 returned 后,浏览器操作将得到解决。事实上,防止默认操作的机制之一(实际上是原始机制)是让事件处理程序 return false0 取消默认操作。所以它是半同步发生的——它发生在一个异步函数中,但在当前事件循环结束时被解决。

解决此问题的唯一方法是在调用您的 promise 之前调用 .preventDefault()