简体   繁体   中英

event.preventDefault() not working inside of .then

Code:

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);
        }
      })
    ;
  });
}

When I'm logged in as a non-admin and I go to localhost:3000/admin :

  1. I get an alert saying, "You must be an admin to access this route."
  2. I get taken to the admin page, and can see all of the admin stuff that I'm not supposed to be able to see.

Why is this?

When I inspect in the debugger, event.preventDefault is defined, and it seems to get called. This is the event object that gets logged out to the console:

在此处输入图片说明

It's defaultPrevented property gets set to true !


UPDATE: It works outside of the .then , but it does NOT work inside of the .then . Which is surprising because it is defined inside of the .then .


UPDATE 2: My guess is that the event does it's default action BEFORE it reaches the .then . And so essentially, .then is too late.

Your second guess is essentially correct. The browser actions are resolved after all the current event handlers have returned. In fact, one of the mechanisms to prevent default action (the original mechanism actually) was to have the event handler return false or 0 to cancel default action. So it happens semi-synchronously - it happens inside an asynchronous function but is resolved at the end of the current event loop.

The only way around it is to call .preventDefault() before calling your promise.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM