Прерывание отправки формы в блоке fetch

Выполняю проверки полей на стороне клиента на пробелы, на лишние символы и тд, в случае одного не совпадения форма не отправляется. Но при fetch запросе на наличие пользователя с данным логином все отрабатывает верно, но все равно форма отправляется. Почему так? я понимаю что проблема в том что fetch запрос асинхронный, но все равно победить это не могу.

<script>
    function validateForm() {
        const userName = document.getElementById("userName").value;
        const password = document.getElementById("password").value;
        const confirmPassword = document.getElementById("confirmPassword").value;
        const firstName = document.getElementById("firstName").value;
        const lastName = document.getElementById("lastName").value;
        let rc = true;

        fetch('/registration/check-username?userName=' + userName)
            .then(response => response.json())
            .then(data => {
                if (!data) {
                    alert("Пользователь с таким логином уже существует");
                    rc = false;
                }
            });

        if (userName.includes(" ") || password.includes(" ") || confirmPassword.includes(" ")
            || firstName.includes(" ") || lastName.includes(" ")) {
            alert("Строки не могут содержать пробелы");
            rc = false;
        }

        const regex1 = /^[A-Za-z0-9]+$/;
        if (!(regex1.test(userName) && regex1.test(password) && regex1.test(confirmPassword))) {
            alert("Логин и пароль могут содержать только английские символы и цифры");
            rc = false;
        }

        const regex2 = /^[А-Яа-я]+$/;
        if (!(regex2.test(firstName) && regex2.test(lastName))) {
            alert("Имя и фамилия могут содержать только русские буквы");
            rc = false;
        }

        if (password !== confirmPassword) {
            alert("Введенные пароли не совпадают");
            rc = false;
        }

        return rc;
    }
</script>

Ответы (2 шт):

Автор решения: Алексей Шиманский

Если вы знаете, что fetch асинхронный, значит надо копать в эту сторону. Конкретнее: смотреть async/await, async/await in docs

В итоге функция будет уже такой:

async function validateForm() {
    ...
}

а работа с fetch примерно такой:

let response = await fetch('/registration/check-username?userName=' + userName);
let data = await response.json();

if (!data) {
    alert("Пользователь с таким логином уже существует");
    rc = false;
}

НО...тут может возникнуть проблема применения validateForm.... в зависимости от того, где она стоИт и как применяется...Потому что функция тоже становится асинхронной и в месте её использования придётся тоже что-то модифицировать. Пример можно посмотреть тут

Опять же, тут придётся погрузиться в тему async/await

→ Ссылка
Автор решения: Faraday

Ну потому что у вас сначала идёт отправка по fetch, а потом уже проверки. Просто измените последовательность. Сначала можете сделать все проверки с сохранением результата, а потом уже делать проверку на то, вернула ли какая-то проверка валидации значение false. Тот же fetch закидывайте в какой-то if/else с условием true от всех валидаций, и только в этом случае делайте отправку

Но если вы используете fetch как серверную валидацию (Что мне подсказали в комментариях), тут есть несколько моментов. Во-первых, отправка данных на сервер должна выполняться через HttpPost запрос. Во вторых, вот стандартная схема для использования fetch:

let response = await fetch('domain.com/url/')
let data = await response.json()

Вот статья о том, как делать fetch запрос

→ Ссылка