如果密码错误,登录表单应该会显示一个警报。但是,它会显示4次警报。
id为‘loginbutton’的按钮触发函数'auth()‘onclick。它在登录和注销时工作正常。但是,当我尝试使用错误的用户名、密码对时,警报消息window.alert(“错误的用户名或密码”)会连续显示四次。这意味着onclick()事件由于某种原因被触发了四次。
在这里,同样的“登录”按钮也可以作为“退出”按钮。我使用函数setLoginButton()来确定用户的当前状态(是否登录),并基于此更新按钮文本。
HTML:
<body onload = "setLoginButton()">
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Lorem</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<form class="navbar-form navbar-right">
<div class="form-group">
<input type="text" placeholder="Username" class="form-control" id="username">
</div>
<div class="form-group">
<input type="password" placeholder="Password" class="form-control" id="password">
</div>
<button type="submit" class="btn btn-success" onclick="auth(event)" id="loginbutton">Sign in</button>
</form>
</div><!--/.navbar-collapse -->
</div>
</nav>
Javascript:
// Init datatables
$(document).ready( function () {
$('#content1').DataTable();
$('#holdTable').hide();
} );
function setLoginButton() {
token = window.sessionStorage.getItem('cicitoken');
if (token == null) {
return false;
}
else {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 400) {
window.sessionStorage.removeItem('cicitoken');
buttonText = "Sign In";
displayForm = "block";
}
else {
buttonText = "Sign Out";
displayForm = "none";
}
document.getElementById("loginbutton").innerHTML = buttonText;
document.getElementById("username").style.display = displayForm;
document.getElementById("password").style.display = displayForm;
};
xhttp.open("POST", "/api-token-verify/", true);
xhttp.setRequestHeader("Content-type", "application/json");
xhttp.send(JSON.stringify({"token": token}));
}
}
//auth function to get token and use sessionstorage
auth = function(e) {
e.preventDefault();
token = window.sessionStorage.getItem('cicitoken');
if ( token != null) {
window.sessionStorage.removeItem('cicitoken');
location.reload()
}
else {
var xhttp = new XMLHttpRequest();
jdata={username:document.getElementById("username").value,password:document.getElementById("password").value};
xhttp.onerror = function(xhr, status, err) {
console.log(err);
}
xhttp.onabort = function(xhr, status, err) {
console.log(err);
}
xhttp.onreadystatechange = function() {
if (xhttp.readyState==4 && xhttp.status==200) {
var response = JSON.parse(xhttp.responseText);
window.sessionStorage.setItem('cicitoken',response.token);
}
else {
window.alert("Wrong username or password");
setLoginButton();
}
setLoginButton();
}
xhttp.open("POST", "/api-token-auth/", true);
xhttp.setRequestHeader("Content-type", 'application/json; charset=UTF-8');
xhttp.send(JSON.stringify(jdata));
}
}
发布于 2018-09-21 21:00:22
XMLHttpRequest将遍历它们的就绪状态。所以它从状态0开始,它将经历每个状态,直到它达到状态4,完成。
由于您的警报绑定到onreadystatechange事件,该事件也将被调用4次:
xhttp.onreadystatechange = function() {
if (xhttp.readyState==4 && xhttp.status==200) {
var response = JSON.parse(xhttp.responseText);
window.sessionStorage.setItem('cicitoken',response.token);
}
else {
window.alert("Wrong username or password");
setLoginButton();
}
setLoginButton();
}
由于警报与条件if readyState !== 4
相关,因此它将显示状态0、1、2和3的警报。
解决方案是将警报包含在if readyState === 4
块中的某个位置,而不是将其放在该块之外。然后,您还可以将警报绑定到XMLHttpRequest的onerror事件,以便在XMLHttpRequest在到达readyState 4之前失败时捕获错误。
这还意味着,您在其他readystatechange处理程序中所做的所有样式更改也会被调用太多次,而不是仅当请求的结果已知时才调用。
发布于 2018-09-22 04:30:16
对于任何面临同样问题的人来说,这是我根据@Shilly的回答修改代码的方式:
xhttp.onreadystatechange = function() {
if (xhttp.readyState==4 && xhttp.status==200) {
var response = JSON.parse(xhttp.responseText);
window.sessionStorage.setItem('cicitoken',response.token);
setLoginButton();
}
else if (xhttp.readyState==4 && xhttp.status==400){
window.alert("Wrong username or password");
setLoginButton();
}
}
https://stackoverflow.com/questions/52444224
复制相似问题