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
:
- 我收到一条警告说,"You must be an admin to access this route."
- 我进入管理页面,可以看到所有我不应该看到的管理内容。
这是为什么?
当我在调试器中检查时,event.preventDefault
已定义,而且它似乎被调用了。这是注销到控制台的 event
对象:
defaultPrevented
属性 设置为 true
!
更新:它在 .then
之外工作,但在 .then
内部不起作用。这是令人惊讶的,因为它是在 .then
.
内部定义的
更新 2:我的猜测是 event
在到达 .then
之前执行默认操作。所以本质上,.then
为时已晚。
你的第二个猜测基本正确。在所有当前事件处理程序都已 returned 后,浏览器操作将得到解决。事实上,防止默认操作的机制之一(实际上是原始机制)是让事件处理程序 return false
或 0
取消默认操作。所以它是半同步发生的——它发生在一个异步函数中,但在当前事件循环结束时被解决。
解决此问题的唯一方法是在调用您的 promise 之前调用 .preventDefault()
。
代码:
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
:
- 我收到一条警告说,"You must be an admin to access this route."
- 我进入管理页面,可以看到所有我不应该看到的管理内容。
这是为什么?
当我在调试器中检查时,event.preventDefault
已定义,而且它似乎被调用了。这是注销到控制台的 event
对象:
defaultPrevented
属性 设置为 true
!
更新:它在 .then
之外工作,但在 .then
内部不起作用。这是令人惊讶的,因为它是在 .then
.
更新 2:我的猜测是 event
在到达 .then
之前执行默认操作。所以本质上,.then
为时已晚。
你的第二个猜测基本正确。在所有当前事件处理程序都已 returned 后,浏览器操作将得到解决。事实上,防止默认操作的机制之一(实际上是原始机制)是让事件处理程序 return false
或 0
取消默认操作。所以它是半同步发生的——它发生在一个异步函数中,但在当前事件循环结束时被解决。
解决此问题的唯一方法是在调用您的 promise 之前调用 .preventDefault()
。