Javascript 使用AJAX验证用户时,获取正确的返回值时出现问题
当用户不正确时,我想为Javascript 使用AJAX验证用户时,获取正确的返回值时出现问题,javascript,html,ajax,Javascript,Html,Ajax,当用户不正确时,我想为okLogin获取正确的值,并阻止表单向前运行,但我注意到,当我调用函数时,返回比ajax调用先执行,ajax调用应该向后执行 我希望ajax函数在出现不匹配时将okLogin变量更新为false <form action="test.html" onsubmit="return loginProcess();"> <label for="usernameLogin" class="col-sm-4 col-form-label">Usern
okLogin
获取正确的值,并阻止表单向前运行,但我注意到,当我调用函数时,返回比ajax调用先执行,ajax调用应该向后执行
我希望ajax函数在出现不匹配时将okLogin变量更新为false
<form action="test.html" onsubmit="return loginProcess();">
<label for="usernameLogin" class="col-sm-4 col-form-label">Username</label>
<input class="form-control" type="text" id="usernameLogin" required>
<label for="passwordLogin" class="col-sm-4 col-form-label">Password</label>
<input class="form-control" type="password" id="passwordLogin" required>
<input type="submit" class="btn btn-primary btn-block" id="loginSubmitBtn" value="Login">
</form>
<script>
function loginProcess() {
let users, usernameLogin, passwordLogin;
let ajaxCall = new XMLHttpRequest();
let okLogin = true;
usernameLogin = document.getElementById("usernameLogin").value;
passwordLogin = document.getElementById("passwordLogin").value;
ajaxCall.onreadystatechange = function() {
if (ajaxCall.readyState == 4 && ajaxCall.status == 200) {
users = JSON.parse(ajaxCall.responseText);
for (let item in users) {
if (item === "username") {
if (usernameLogin !== users["username"]) {
okLogin = false;
}
console.log("Username: " + okLogin);
}
if (item === "password") {
if (passwordLogin !== users["password"]) {
okLogin = false;
}
}
}
}
}
ajaxCall.open("GET", "docs/users.json", true);
ajaxCall.send();
return okLogin;
}
</script>
用户名
密码
函数loginProcess(){
让用户、用户名登录、密码登录;
设ajaxCall=new XMLHttpRequest();
让okLogin=true;
usernameLogin=document.getElementById(“usernameLogin”).value;
passwordLogin=document.getElementById(“passwordLogin”).value;
ajaxCall.onreadystatechange=函数(){
if(ajaxCall.readyState==4&&ajaxCall.status==200){
users=JSON.parse(ajaxCall.responseText);
for(让项目进入用户){
如果(项目==“用户名”){
if(usernameLogin!==users[“username”]){
okLogin=false;
}
console.log(“用户名:”+okLogin);
}
如果(项目==“密码”){
if(passwordLogin!==用户[“密码”]){
okLogin=false;
}
}
}
}
}
打开(“GET”,“docs/users.json”,true);
ajaxCall.send();
返回okLogin;
}
这将不起作用,因为ajax请求是异步的。换句话说,onreadystatechange
中的代码只有在ajax调用返回后才被定义为稍后执行。这就是为什么您的方法在ajax调用完成之前返回
我还要指出,身份验证是正确进行的一件重要事情,我认为您最好看看一些正确身份验证的示例。从外观上看,您正在以明文形式返回呼叫中所有用户名和密码的列表。这是一个非常不安全的设计。如果你打算把它用于实验以外的任何事情,你不应该这样做。事实上,即使你只是把它作为一个实验,我建议你尝试用不同的方式去做,只是为了获得经验去做应该做的事情
无论如何,让它按原样工作的方法是,在回调中采取一些操作,而不是返回。在您提交的代码中,当loginProcess
方法返回时,不清楚会发生什么(从外观上看,什么也没有发生)。也许,您可以使用onreadystatechange
函数调用其他方法,并使用true或false,让该函数处理基于成功或不成功登录应该发生的任何事情
例如:
ajaxCall.onreadystatechange = function() {
if (ajaxCall.readyState == 4 && ajaxCall.status == 200) {
[your code to check the login here]
someOtherFunction(okLogin)
}
}
另外,我建议您研究一种更现代的处理ajax请求的方法,欢迎使用。您的问题是由于异步JavaScript的性质造成的。XMLHTTPRequest需要一些时间才能得到响应。因此,在返回值之前需要等待,直到请求完成。现在,您立即返回
okLogin
,而请求没有机会更改它
所以你需要推迟。您可以使用async
/wait
等待请求完成并继续处理。这一切都基于一个对象,该对象可以使用then
方法将回调链接在一起
不要使用XMLHTTPRequest
构造函数,而是尝试使用。这是同一原则的更现代版本,但有一个更简单、更强大的工作流程,并且它与承诺一起工作
现在使用async/await,您可以使函数异步,这意味着它需要一些时间才能完成,但在完成后要做一些其他事情。await
关键字可以放在任何承诺返回函数(如fetch)前面,以等待函数完成并从中获取值
在您的代码中,它看起来是这样的
async function loginProcess() {
let usernameLogin, passwordLogin, response, users;
let okLogin = true;
usernameLogin = document.getElementById("usernameLogin").value;
passwordLogin = document.getElementById("passwordLogin").value;
response = await fetch("docs/users.json");
users = await response.json();
for (let item in users) {
if (item === "username" && usernameLogin !== item) {
okLogin = false;
} else if (item === "password" && passwordLogin !== item) {
okLogin = false;
}
}
return okLogin;
}
该函数使用fetch
获取数据,等待数据完成,然后将JSON的结果转换为可用值,并从那里继续。
由于loginProcess
本身是异步的,因此它会返回一个承诺。仔细阅读你如何使用它们。它们是JavaScript的一个非常强大的功能
还要注意@bodicious。关于代码中的安全问题,他提出了一些非常好的观点。执行验证服务器端,其中代码对用户不可见。编写时,代码将始终返回true;您定义为true的
okLogin
的值将是除此之外的任何值。这是因为ajaxCall.send()
是异步的:它启动了AJAX调用,但仅此而已;它不会等待调用成功(或失败)。因此,接下来发生的事情是,每次调用ajaxCall.send()
,都返回当前值okLogin
,每次都是真的,因为任何可能更改其值的代码都不会被执行。(只有在您的AJAX请求得到响应后才会执行)希望这是有意义的;在处理像send()
这样的异步方法时,这是一个常见的错误,这些方法启动某些东西(在本例中是AJAX请求),但不等待它完成后再返回。(在您的情况下,每次返回的值都是true,因为每次返回okLogin
后,ajaxCall.onreadystatechange
函数中的代码都会执行)
一种解决方案是通过将false
而不是true
作为open()
的最后一个参数,使AJAX调用同步。这会奏效,但这是一个严重的坏主意;做同步AJAX是非常困难的
loginProcess().then((loginStatus) => {
console.log(loginStatus)
});
<form action="test.html" onsubmit="return loginProcess();">
<form class="main-form" action="test.html" onsubmit="loginProcess(); return false;">
ajaxCall.onreadystatechange = function() {
if (ajaxCall.readyState == 4 && ajaxCall.status == 200) {
users = JSON.parse(ajaxCall.responseText);
for (let item in users) {
if (item === "username") {
if (usernameLogin !== users["username"]) {
okLogin = false;
}
console.log("Username: " + okLogin);
}
if (item === "password") {
if (passwordLogin !== users["password"]) {
okLogin = false;
}
}
}
// ***** Add the following three lines:
if (okLogin) {
document.querySelector('form.main-form').submit()
}
}
}