实现HTML/JavaScript表单异步提交 解决邮箱重复校验提前返回问题
问题根源
- 原生
onsubmit属性绑定的处理器无法识别异步函数的返回值:async函数执行后会立刻返回Promise对象,浏览器会将这个对象判定为真值,直接触发表单提交,根本不会等待内部的异步邮箱校验请求执行完成。 - 全局变量
ret没有在每次提交时重置:上一次校验的失败状态会残留到下一次提交,导致校验结果异常。 - 混用jQuery Ajax的
success回调和await写法,存在时序问题,无法保证ret的赋值在return语句之前完成。
修复步骤
- 移除form标签上内联的
onsubmit绑定,改为在JS中绑定提交事件,先调用event.preventDefault()阻止默认提交行为,等所有校验完成后再手动触发表单提交。 - 移除全局的
ret变量,每次提交时在函数内部初始化局部校验状态变量,避免跨次提交的状态污染。 - 去掉Ajax的
success回调,直接通过await获取接口返回的用户数据,在异步请求完成后再执行邮箱重复校验逻辑,保证执行顺序。
修正后完整代码
<html> <head> <script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script> </head> <body> <form id='form' action="/signup.html" method="POST"> <div style="text-align:center"> <label for="name">Full Name</label><br> <input type="text" size="100" id="name" name="name" placeholder="Enter Your Full Name: "><br><br> <label for="email">Email</label><br> <input type="text" size="100" id="email" name="email" placeholder="Enter Your Email: "><br><br> <label for="password">Password</label><br> <input type="text" size="100" id="password" name="password" placeholder="Enter Your Password: "><br><br> <button type="submit" id="submit">Submit</button> </div> </form> <script type="text/javascript"> const form = document.getElementById('form'); form.addEventListener('submit', async function(e) { // 先阻止默认提交行为 e.preventDefault(); // 每次提交初始化校验状态,不用全局变量 let valid = true; const nameInput = document.getElementById("name"); const emailInput = document.getElementById("email"); const passwordInput = document.getElementById("password"); const name = nameInput.value.trim(); const email = emailInput.value.trim(); const password = passwordInput.value; // 基础输入校验 if (name.length < 4) { nameInput.value = ""; nameInput.placeholder = "Please enter a real name"; valid = false; } let emailFormatValid = false; if (email.length < 4) { emailInput.value = ""; emailInput.placeholder = "Please enter a real email"; valid = false; } else { for (let i = 0; i < email.length; i++) { if (email[i] == '@') { emailFormatValid = true; break; } } if (!emailFormatValid) { emailInput.value = ""; emailInput.placeholder = "Please enter a real email"; valid = false; } } if (password.length < 5) { passwordInput.value = ""; passwordInput.placeholder = "Password must be atleast 5 characters."; valid = false; } // 基础校验不通过直接返回,不用发请求 if (!valid) return; // 异步校验邮箱重复,await拿到返回结果后再处理 const userContent = await $.ajax({ type: "POST", url: '/getUsers', dataType: "text" }); const userList = userContent.split('\n'); for (let i = 0; i < userList.length; i += 3) { if (userList[i] == email) { emailInput.value = ""; emailInput.placeholder = "Email already in use."; valid = false; break; } } // 所有校验通过才提交表单 if (valid) { form.submit(); } }) </script> </body> </html>
额外优化点:基础校验不通过时直接终止后续逻辑,不需要发送重复邮箱校验的接口请求,减少不必要的网络开销;遍历用户列表匹配到重复邮箱后直接break终止循环,不需要遍历完所有数据。
内容的提问来源于stack exchange,提问作者Daniel Zamloot
相关产品推荐
相关产品推荐

