I have a sign up form and I have a javascript function while validates the form input with a fetch request to a php file. The code is as follows:
form.onsubmit = function() {
let signInData = JSON.stringify(Object.fromEntries(new FormData(form).entries()));
let flag = false;
fetch('php/sign_up.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: signInData,
})
.then(response => response.text())
.then(data => {
if(data != "1") {
document.getElementById("sign_up_error").innerHTML = data;
flag = false;
} else {
flag = true;
}
});
return flag
};
Now the fetch command requires some time to finish and the .onsubmit function returns a value before it completes. Now I know that an asynchronous function can be used to wait for the fetch to finish using async-await, but have a look. Let's visualize the code for the form:
if(form.onsubmit()) {
sendFormData();
}
As you can see, they don't use an asynchronous function on their side to get the data, they use a synchronous function. On their side, form.onsubmit() would evaluate to an empty promise. And an empty promise as a boolean is true, so it would always just send the data. And I cannot use callback since the value has to be returned in that function itself.
CodePudding user response:
- Use async await instead of promise chaining
- You don't need to set flag to false when it already is false at the top
- Hoist your functions for event listeners, it's better practice
- Use !== instead of !=
const handleSubmit = async (e) => {
let signInData = JSON.stringify(
Object.fromEntries(new FormData(form).entries())
);
let flag = false;
const response = await fetch('php/sign_up.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: signInData,
});
const toText = await response.text();
if (toText !== '1'){
document.getElementById('sign_up_error').innerHTML = toText
return flag;
} else {
return flag = true;
}
};
form.onsubmit(handleSubmit);
CodePudding user response:
async
function is executed asynchronously if it includes await
expression. The function is asynchronously completed at the await
expression, returning Promise (not boolean).
So, we cannot execute the callback function synchronously if it includes fetch
function that needs await
expression.
Refer https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function.
I think the alternative is the following. The callback always cancel the submission, and then, when your validation process succeed, submit the form.
form.addEventListener('submit', (e) => {
e.preventDefault(); // cancel submission
let signInData = JSON.stringify(Object.fromEntries(new FormData(form).entries()));
fetch('php/sign_up.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: signInData,
})
.then(response => response.text())
.then(data => {
if(data != "1") {
document.getElementById("sign_up_error").innerHTML = data;
} else {
form.submit();
}
});
};