JS中使用XMLHttpRequest的函数如何返回布尔值给调用函数
背景
我有一个包含用户名、密码、确认密码三个输入项的表单,需要用JavaScript做规则校验(比如密码最小长度等),所以我实现了*validateForm()函数来完成校验逻辑。
其中一项校验规则是用户名不能重复,我又单独实现了userExists()函数供validateForm()*调用。*userExists()*本身运行正常,控制台可以正确打印"Exists"或"Does not exist"。
问题描述
但我无法将*userExists()返回的用户是否存在的布尔值(true/false)传递到validateForm()函数中。
我的核心问题是:**如何将用户是否存在的判断结果从userExists()传递到validateForm()中?*
我是JavaScript新手,这个问题已经卡了一整天了,不知道怎么解决,非常希望能得到帮助。
已尝试的解决方案
我在console.log("Exists / Does not exist")下方分别添加了return true;和return false;,但在validateForm()中调用userExists()时拿到的不是布尔值,而是undefined。
我也尝试了很多异步函数相关的解决方案,比如用布尔变量存储结果、Callbacks、timeout、await(当前编辑器不允许使用await)等方案,都没有解决问题。
现有代码如下:
function validateForm() { // 其他校验逻辑 // 尝试获取userExists()的布尔返回值并给出对应提示(实际userExists()返回undefined,无法生效) else if(userExists()){ alert("用户名已被使用"); name = ""; return false; } // 其他校验逻辑 } function userExists() { var xmlhttp = new XMLHttpRequest(); xmlhttp.onreadystatechange = function () { if (xmlhttp.readyState == 4) { if (xmlhttp.status == 204) { // 控制台打印正常,但布尔值无法返回 console.log("Exists"); return true; } else if (xmlhttp.status == 404) { console.log("Does not exist"); return false; } } } xmlhttp.open("GET", "#someLink", true); xmlhttp.send(); }
解决方案
核心原因说明
你遇到的是典型的异步调用返回值问题:
- 你写的
return true/return false是属于onreadystatechange回调函数的返回值,不是外层userExists函数的返回值 - XMLHttpRequest默认是异步执行的,
userExists函数调用send()之后就直接执行结束了,不会等待网络请求返回,所以userExists天然没有返回值,拿到的就是undefined
适配场景修改方案(无需await)
使用回调函数传递结果即可,修改后代码如下:
// 首先修改validateForm,把依赖用户是否存在的逻辑放到回调中 function validateForm() { // 其他同步校验逻辑(比如密码长度、两次密码是否一致)优先执行 // 其他校验都通过后,调用userExists处理用户名重复校验 userExists(function(isExist) { if(isExist) { alert("用户名已被使用"); name = ""; return false; } // 用户名不存在,走后续表单提交逻辑 // 示例:document.getElementById("yourFormId").submit(); }) } // 修改userExists,接收回调函数作为参数,请求完成后调用回调传递结果 function userExists(callback) { var xmlhttp = new XMLHttpRequest(); xmlhttp.onreadystatechange = function () { if (xmlhttp.readyState == 4) { if (xmlhttp.status == 204) { console.log("Exists"); callback(true); } else if (xmlhttp.status == 404) { console.log("Does not exist"); callback(false); } } } xmlhttp.open("GET", "#someLink", true); xmlhttp.send(); }
方案说明
- 不再尝试让
userExists直接返回布尔值,而是给它传入一个回调函数,等异步请求拿到结果之后,主动调用这个回调函数,把结果作为参数传进去 - 原本
validateForm里依赖用户是否存在的逻辑,都放到这个回调函数里执行,就能保证逻辑执行时已经拿到了请求结果 - 如果有其他校验分支,你可以把表单校验通过后的提交逻辑也封装成单独的函数,在所有校验都通过后调用即可
内容的提问来源于stack exchange,提问作者butterfly
相关产品推荐
相关产品推荐

