Магия AJAX: Как отправлять формы без перезагрузки страницы с помощью Fetch API

Магия AJAX: Как отправлять формы без перезагрузки страницы с помощью Fetch API

Представьте себе: пользователь заполняет длинную форму регистрации, нажимает «Отправить» и... страница не мигает, не перезагружается, а данные тихо улетают на сервер, а на месте формы появляется зелёная галочка. Это не волшебство, а современный подход к работе с веб-формами с использованием JavaScript и Fetch API. В этой статье мы разберём, как заменить устаревший метод отправки через перезагрузку на плавный, быстрый и удобный для пользователя AJAX-запрос.

Почему Fetch, а не старый добрый XMLHttpRequest?

Раньше для асинхронных запросов использовался громоздкий XMLHttpRequest (XHR). Fetch API — это его современная, более чистая и мощная замена, основанная на промисах (Promises). Он встроен в браузер и позволяет работать с HTTP-запросами гораздо элегантнее.

Ключевое преимущество: Fetch возвращает Promise, что позволяет использовать цепочки .then() и .catch() или async/await для удобной обработки асинхронных операций.

Базовый шаблон отправки формы с Fetch

Вот минимальный рабочий код, который отменит стандартную отправку формы и отправит данные асинхронно.

1. HTML-форма

Главное — не забыть про event.preventDefault(), чтобы браузер не пытался перезагрузить страницу.

2. JavaScript с Fetch

Создадим обработчик события submit для формы:

document.getElementById('myForm').addEventListener('submit', async function(event) {
    event.preventDefault(); // Останавливаем стандартную отправку

    // Собираем данные формы
    const formData = new FormData(this);

    try {
        // Отправляем POST-запрос
        const response = await fetch('/submit.php', {
            method: 'POST',
            body: formData // Можно также отправлять как JSON: body: JSON.stringify(Object.fromEntries(formData))
        });

        // Проверяем, что ответ успешный (статус 200-299)
        if (!response.ok) {
            throw new Error(`Ошибка HTTP: ${response.status}`);
        }

        // Парсим ответ (предполагаем JSON)
        const result = await response.json();

        // Обрабатываем успех
        console.log('Успех!', result);
        alert('Форма отправлена!');
        this.reset(); // Очищаем форму

    } catch (error) {
        // Обрабатываем ошибки (сеть, парсинг, статус не OK)
        console.error('Ошибка:', error);
        alert('Произошла ошибка при отправке.');
    }
});

Важно: Всегда обрабатывайте ошибки в блоке catch. Промис, возвращаемый fetch(), отклоняется (rejects) только при сбое сети или если что-то помешало выполнению запроса. Ошибки HTTP, такие как 404 или 500, считаются успешными для промиса, поэтому критически важно проверять свойство response.ok или response.status.

Расширенные возможности и лучшие практики

Отправка JSON вместо FormData

Если ваш сервер ожидает JSON, конвертируйте данные:

const data = Object.fromEntries(new FormData(this));
const response = await fetch('/api/submit', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json'
    },
    body: JSON.stringify(data)
});

Индикация загрузки

Покажите пользователю, что запрос выполняется:

const submitBtn = this.querySelector('button[type="submit"]');
const originalText = submitBtn.textContent;
submitBtn.textContent = 'Отправляем...';
submitBtn.disabled = true;

// ... внутри finally блока после try/catch:
finally {
    submitBtn.textContent = originalText;
    submitBtn.disabled = false;
}

Обработка различных типов ответов

Fetch может работать не только с JSON:

  • response.text() — для простого текста или HTML.
  • response.blob() — для файлов (например, скачивание PDF).
  • response.formData() — для данных формы.

FAQ: Часто задаваемые вопросы

Чем Fetch лучше обычной отправки формы?

Он обеспечивает бесшовный пользовательский опыт (без «моргания» страницы), позволяет гибко обрабатывать ответы и ошибки, а также отправлять данные в разных форматах (JSON, FormData).

Будет ли это работать в старых браузерах?

Fetch поддерживается всеми современными браузерами. Для поддержки Internet Explorer потребуется полифил (например, whatwg-fetch).

Как обработать ошибку валидации с сервера (статус 422)?

Проверьте статус ответа. Если response.status === 422, распарсите ответ (обычно JSON с массивом ошибок) и отобразите их пользователю рядом с полями формы.

Можно ли отправлять файлы через Fetch?

Да, для этого используйте объект FormData. Он автоматически правильно установит заголовки и кодировку для передачи файлов.

В чём разница между Fetch и Axios?

Axios — это популярная сторонняя библиотека. Она предоставляет более удобный API (например, автоматическую трансформацию JSON), встроенную защиту от XSRF и обратную совместимость с IE. Fetch — нативное браузерное решение, более легковесное.