The asynchronous request in JS cannot be returned to the correct Boolean value of the method - solution
1. Problem phenomenon
The problem of normal ajax verification: the boolean value false cannot be returned correctly, so the form submission cannot be blocked correctly!!!
// Normal ajax asynchronous request (verify that the user name is the same as in the database) $.ajax({ type : "post", async : true, url : "<%=request.getContextPath()%>/validateLogin", // Duplicate lookup Servlet data : { "username" : name }, success : function(data) { console.log("data:" + data + ", type:" + (typeof data)); // Contrary to the login logic, the false user does not exist, and the true user exists (unable to register) if (data == false) { nameSpan.innerHTML = "√".fontcolor("green"); result = true; } else { nameSpan.innerHTML = "User name already exists".fontcolor("red"); result = false; } }, dataType: "json", });
Therefore, the current needs are very clear:
How to get a return value correctly in the function(data) of ajax asynchronous request callback function for form submission / interception.
Through further research and verification, there are two solutions:
- Mode 1: take ajax as a verification event for temporary synchronization, and correctly assign the required return value
- Mode 2: use the custom get/set method to ensure that the operation is always the same variable (that is, the return value that needs to be correctly assigned)
2. Solution 1: change async to temporary synchronization + variable assignment
jQuery.ajax() parameter: async
- Type: Boolean
- Default value: true. By default, when there is no async parameter, all requests are asynchronous. Explicitly set to false is the synchronization request.
- Note that the synchronization request will lock the browser, and other operations of the user must wait for the request to be completed before execution.
// Method 1: take ajax as a verification event for temporary synchronization, and correctly assign the required return value result function checkStuName1() { // If the ID tag does not exist, id === undefined, and. value cannot be operated directly var id = document.getElementsByName("stuId")[0]; var name = document.getElementsByName("username")[0].value; var nameSpan = document.getElementById("nameSpan"); console.log("id:" + id + ", " + "name:" + name); if (null === name || "" === name) { nameSpan.innerHTML = "* User name cannot be empty".fontcolor("red"); return false; } var result; if (undefined === id || null === id || "" === id) { // register $.ajax({ type : "post", async : false, // Change to synchronous request + result variable url : "<%=request.getContextPath()%>/validateLogin", data : { "username" : name }, success : function(data) { console.log("data:" + data + ", type:" + (typeof data)); // Contrary to the login logic, the false user does not exist, and the true user exists (unable to register) if (data == false) { nameSpan.innerHTML = "√".fontcolor("green"); result = true; } else { nameSpan.innerHTML = "User name already exists".fontcolor("red"); result = false; } }, dataType: "json", }); } else { // id is not empty: modify operation console.log("Modify operation"); result = false; } return result; }
3. Solution 2: use global variable + Write get/set method
// Mode 2: use the custom get/set method to ensure that the operation is always the same flag (that is, the return value that needs to be correctly assigned) var flag = false; function getFlag() { return flag; } function setFlag(b) { flag = b; } function checkStuName2() { // If the ID tag does not exist, id === undefined, and. value cannot be operated directly var id = document.getElementsByName("stuId")[0]; var name = document.getElementsByName("username")[0].value; var nameSpan = document.getElementById("nameSpan"); console.log("id:" + id + ", " + "name:" + name); if (null === name || "" === name) { nameSpan.innerHTML = "* User name cannot be empty".fontcolor("red"); return false; } if (undefined === id || null === id || "" === id) { // register $.post("<%=request.getContextPath()%>/validateLogin", { "username": name }, function(data) { console.log("data:" + data + ", type:" + (typeof data)); // Contrary to login logic, true user exists false user does not exist if (data == true) { nameSpan.innerHTML = "User name already exists".fontcolor("red"); setFlag(false); } else { nameSpan.innerHTML = "√".fontcolor("green"); setFlag(true); } }, "json"); } else { // modify console.log("Modify operation"); } console.log("final flag=" + getFlag()); return getFlag(); }
4. demo source code
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>register/Modify page</title> <script src="${pageContext.request.contextPath}/js/jquery-3.5.1.min.js"></script> <script type="text/javascript"> function show(file) { var reader = new FileReader(); // Instantiate a FileReader object for reading files var img = document.getElementById('img'); // Get the label of the picture to display //Read data from File object reader.onload = function(evt) { img.width = "50"; img.height = "50"; img.src = evt.target.result; } reader.readAsDataURL(file.files[0]); } // Method 1: take ajax as a verification event for temporary synchronization, and correctly assign the required return value result function checkStuName1() { // If the ID tag does not exist, id === undefined, and. value cannot be operated directly var id = document.getElementsByName("stuId")[0]; var name = document.getElementsByName("username")[0].value; var nameSpan = document.getElementById("nameSpan"); console.log("id:" + id + ", " + "name:" + name); if (null === name || "" === name) { nameSpan.innerHTML = "* User name cannot be empty".fontcolor("red"); return false; } var result; if (undefined === id || null === id || "" === id) { // register $.ajax({ type : "post", async : false, // Change to synchronous request + result variable url : "<%=request.getContextPath()%>/validateLogin", data : { "username" : name }, success : function(data) { console.log("data:" + data + ", type:" + (typeof data)); // Contrary to the login logic, the false user does not exist, and the true user exists (unable to register) if (data == false) { nameSpan.innerHTML = "√".fontcolor("green"); result = true; } else { nameSpan.innerHTML = "User name already exists".fontcolor("red"); result = false; } }, dataType: "json", }); } else { // id is not empty: modify operation console.log("Modify operation"); result = false; } return result; } // Mode 2: use the custom get/set method to ensure that the operation is always the same flag (that is, the return value that needs to be correctly assigned) var flag = false; function getFlag() { return flag; } function setFlag(b) { flag = b; } function checkStuName2() { // If the ID tag does not exist, id === undefined, and. value cannot be operated directly var id = document.getElementsByName("stuId")[0]; var name = document.getElementsByName("username")[0].value; var nameSpan = document.getElementById("nameSpan"); console.log("id:" + id + ", " + "name:" + name); if (null === name || "" === name) { nameSpan.innerHTML = "* User name cannot be empty".fontcolor("red"); return false; } if (undefined === id || null === id || "" === id) { // register $.post("<%=request.getContextPath()%>/validateLogin", { "username": name }, function(data) { console.log("data:" + data + ", type:" + (typeof data)); // Contrary to login logic, true user exists false user does not exist if (data == true) { nameSpan.innerHTML = "User name already exists".fontcolor("red"); setFlag(false); } else { nameSpan.innerHTML = "√".fontcolor("green"); setFlag(true); } }, "json"); } else { // modify console.log("Modify operation"); } console.log("final flag=" + getFlag()); return getFlag(); } // Check return function checkAll() { //return checkStuName1(); return checkStuName2(); } </script> </head> <body> <form action="<%=request.getContextPath()%>/addOrUpdate" method="post" enctype="multipart/form-data" onsubmit="return checkAll()"> <table> <c:if test="${null != stuData.stuId}"> <tr> <td>number</td> <td> <input type="text" name="stuId" readonly="readonly" value="${stuData.stuId}"> </td> <td></td> </tr> </c:if> <tr> <td>full name</td> <td> <input type="text" name="username" value="${stuData.stuName}" onblur="checkStuName2()"> </td> <td><span id="nameSpan"></span></td> </tr> <tr> <td>Age</td> <td> <input type="text" name="age" value="${stuData.stuAge}"> </td> <td></td> </tr> <tr> <td>hobby</td> <td> <input type="text" name="hobby" value="${stuData.stuHobby}"> </td> <td></td> </tr> <tr> <td>class</td> <td> <select name="grade"> <option value="1" <c:if test="${stuData.gId==1}">selected</c:if>>zz2001</option> <option value="2" <c:if test="${stuData.gId==2}">selected</c:if>>zz2002</option> <option value="3" <c:if test="${stuData.gId==3}">selected</c:if>>zz2003</option> <option value="4" <c:if test="${stuData.gId==4}">selected</c:if>>zz2004</option> <option value="5" <c:if test="${stuData.gId==5}">selected</c:if>>zz2005</option> </select> </td> <td></td> </tr> <tr> <td>password</td> <td><input type="password" name="password" value="${stuData.pwd}"></td> <td></td> </tr> <tr> <td>birthday</td> <td><input type="date" name="birthday" value="${stuData.stuBirthday}"></td> <td></td> </tr> <tr> <td>head portrait</td> <td> <c:choose> <c:when test="${not empty stuData.imgPath}"> <img id="img" height="50px" width="50px" alt="With a head" src="http://localhost:8081/uploadfile/images/${stuData.imgPath}"> </c:when> <c:otherwise> <img id="img" height="50px" width="50px" alt="With a head" src="<%=request.getContextPath()%>/img/default.png"> </c:otherwise> </c:choose> </td> <td> <input type="file" name="imgPath" onchange="show(this)"> </td> </tr> </table> <input type="submit" value="register"> <input type="reset" value="Reset"> </form> </body> </html>