The asynchronous request in JS cannot be returned to the correct Boolean value of the method - solution

Keywords: JSON JQuery Java Database

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>

Posted by jakeruston on Sat, 06 Jun 2020 00:19:20 -0700