Как отправить данные HTML-формы с помощью JavaScript fetch()

HTML form submit fetch javascript tutorial showing code editor with fetch API call and form submission flow

Если ты когда-либо создавал контактную форму и наблюдал, как вся страница перезагружается после нажатия пользователем кнопки "Отправить", то уже знаешь, насколько неприятным может быть такой опыт. Используя техники отправки HTML форм через fetch javascript, ты можешь отправлять данные формы на backend в фоновом режиме, оставляя пользователя на той же странице и показывая аккуратное сообщение об успехе или ошибке без полной перезагрузки страницы. Это руководство проведет тебя через каждый шаг, от написания базового HTML до настройки вызова fetch() с endpoint от Sendform, чтобы твои заявки попадали прямо в почтовый ящик или подключенный рабочий процесс.

Ключевые моменты:

  • Fetch API позволяет отправлять данные формы без перезагрузки страницы, обеспечивая более плавный пользовательский опыт.
  • Перехват события submit и вызов preventDefault() — основа любой ajax отправки формы.
  • Sendform предоставляет готовый URL endpoint, поэтому тебе не нужен никакой backend код для получения и хранения заявок.
  • Правильная обработка ответа (показ уведомлений об успехе или ошибке) так же важна, как и корректная отправка данных.

Почему использовать fetch() вместо стандартной отправки формы

Стандартное поведение браузера при отправке формы делает ровно одну вещь: сериализует поля формы, отправляет POST (или GET) запрос на URL из атрибута action, а затем загружает ответ сервера. Это означает, что пользователь видит белую вспышку, теряет позицию прокрутки и ждет отрисовки новой страницы. При медленном соединении это может выглядеть как поломка.

Fetch API решает эту проблему, делая HTTP запросы программно, полностью в JavaScript, без перехода на другую страницу. Это позволяет реализовать паттерн отправки формы без перезагрузки страницы, который удерживает пользователей и дает тебе полный контроль над каждым аспектом пользовательского опыта, включая состояния загрузки, встроенную валидацию и анимированные баннеры успеха.

Дополнительные практические причины предпочесть fetch():

  • Ты можешь добавлять пользовательские заголовки (например, CSRF токен или ключ авторизации), которые обычная HTML форма отправить не может.
  • Ты можешь сериализовать данные как JSON, FormData или URL-encoded строки в зависимости от того, что ожидает endpoint.
  • Обработка ошибок явная. Ты сам решаешь, что означает "неудача" и как об этом сообщить.
  • Это работает на любом статическом сайте, включая размещенные на GitHub Pages, Netlify или CDN, потому что логика полностью находится в браузере.

Примечание: Если ты работаешь с конструктором сайтов вроде Webflow, WordPress или Hugo, тот же подход с fetch() применим. Посмотри наше руководство по интеграции Sendform с конструктором сайтов для советов по конкретным платформам.

Базовая настройка HTML формы

Перед написанием единой строчки JavaScript тебе нужна хорошо структурированная HTML форма. Ключевой момент здесь в том, что тебе не нужен атрибут action, указывающий куда-либо, потому что JavaScript будет обрабатывать отправку. Однако тебе нужны осмысленные атрибуты name на каждом input — они становятся ключами полей в отправляемых данных.

<form id="contact-form" novalidate>
  <div>
    <label for="name">Ваше имя</label>
    <input type="text" id="name" name="name" required placeholder="Иван Иванов">
  </div>

  <div>
    <label for="email">Email адрес</label>
    <input type="email" id="email" name="email" required placeholder="[email protected]">
  </div>

  <div>
    <label for="message">Сообщение</label>
    <textarea id="message" name="message" rows="5" required></textarea>
  </div>

  <button type="submit">Отправить сообщение</button>

  <!-- Область для уведомлений -->
  <div id="form-feedback" aria-live="polite"></div>
</form>

Несколько моментов, на которые стоит обратить внимание в этой разметке:

  • novalidate на элементе формы отключает нативные всплывающие подсказки валидации браузера, давая тебе полный контроль над сообщениями об ошибках в JavaScript.
  • Div с id="form-feedback" и aria-live="polite" — это место, где будут появляться сообщения об успехе и ошибках. ARIA атрибут обеспечивает автоматическое объявление уведомлений программами чтения с экрана.
  • Каждый input имеет и id (для связи с label), и name (для данных формы).

Перехват события отправки

Первый шаг в любой javascript отправке формы — это перехват стандартного поведения браузера. Ты делаешь это, слушая событие submit на элементе формы и немедленно вызывая event.preventDefault().

const form = document.getElementById('contact-form');

form.addEventListener('submit', async function (event) {
  event.preventDefault(); // Останавливаем стандартную навигацию

  // Базовая валидация на клиенте
  const name = form.elements['name'].value.trim();
  const email = form.elements['email'].value.trim();
  const message = form.elements['message'].value.trim();

  if (!name || !email || !message) {
    showFeedback('Пожалуйста, заполни все поля.', 'error');
    return;
  }

  // Переходим к отправке данных (следующий раздел)
  await submitForm({ name, email, message });
});

Разделяя логику валидации и сетевой вызов, ты делаешь код читаемым и легко расширяемым. Ключевое слово async на обработчике события позволяет использовать await внутри него, что делает вызов Fetch API похожим на синхронный и избегает глубоко вложенных цепочек промисов.

Настройка fetch() для работы с Sendform endpoint

Здесь происходит настоящая работа. Вместо создания собственного сервера для получения, хранения и пересылки заявок из форм, ты можешь использовать Sendform как свой backend. После создания формы в панели Sendform ты получаешь уникальный URL endpoint. Этот URL — все, что тебе нужно.

Функция отправки ниже использует FormData API для создания данных, которые Sendform принимает нативно:

async function submitForm(data) {
  // Замени этот URL на твой реальный Sendform endpoint
  const SENDFORM_ENDPOINT = 'https://sendform.net/ru/YOUR_FORM_ID';

  const formData = new FormData();
  formData.append('name', data.name);
  formData.append('email', data.email);
  formData.append('message', data.message);

  try {
    const response = await fetch(SENDFORM_ENDPOINT, {
      method: 'POST',
      body: formData,
    });

    if (response.ok) {
      showFeedback('Спасибо! Твое сообщение отправлено.', 'success');
      form.reset();
    } else {
      const errorData = await response.json().catch(() => ({}));
      const errorMsg = errorData.message || 'Что-то пошло не так. Попробуй еще раз.';
      showFeedback(errorMsg, 'error');
    }
  } catch (networkError) {
    showFeedback('Ошибка сети. Проверь соединение и попробуй снова.', 'error');
  }
}

Ключевые решения, принятые в этом коде:

  • Заголовок Content-Type не устанавливается вручную. Когда ты передаешь объект FormData как body, браузер автоматически устанавливает правильную границу multipart/form-data.
  • Проверка response.ok покрывает все HTTP статус коды 2xx, не только 200. Это более надежно, чем сравнение response.status === 200.
  • Внешний try/catch ловит ошибки сетевого уровня (DNS ошибки, офлайн состояние), которые response.ok никогда не увидит.
Поток отправки формы JavaScript fetch к Sendform endpoint URL

Обработка ответа - сообщения об успехе и ошибках

Отправка данных — это только половина работы. Пользователям нужна немедленная, понятная обратная связь. Вспомогательная функция showFeedback(), упомянутая выше, записывает сообщение в div для уведомлений, который ты добавил в HTML:

function showFeedback(message, type) {
  const feedbackEl = document.getElementById('form-feedback');
  feedbackEl.textContent = message;
  feedbackEl.className = type === 'success' ? 'feedback-success' : 'feedback-error';
}

Это намеренно минимально. В реальном проекте ты можешь заменить textContent на анимированный компонент или библиотеку toast уведомлений, но паттерн остается тем же: обновляй DOM на основе результата вызова fetch().

Для более продвинутых сценариев, таких как перенаправление на пользовательскую страницу благодарности или запуск последующей автоматизации после отправки, ознакомься с нашей статьей о том, как автоматизировать рабочие процессы форм с помощью вебхуков, Zapier и API.

Лучшие практики и советы

Заставить код работать — одно дело. Внедрить его так, чтобы он выдержал продакшн — другое. Вот самые важные советы, которые стоит помнить:

  • Отключай кнопку отправки во время запроса. Устанавливай button.disabled = true перед вызовом fetch() и включай снова в блоке finally. Это предотвращает дублирующие отправки, если пользователь кликает несколько раз.
  • Показывай состояние загрузки. Меняй текст кнопки на "Отправляется..." или добавляй класс спиннера, пока запрос в полете. Пользователи, которые не видят обратной связи, часто думают, что ничего не произошло, и кликают снова.
  • Валидируй и на серверной стороне тоже. Клиентская валидация нужна для пользовательского опыта. Sendform и любой backend сервис должны рассматривать все входящие данные как недоверенные.
  • Используй HTTPS везде. Отправка данных формы по обычному HTTP раскрывает пользовательский ввод при передаче. Sendform endpoint по умолчанию используют HTTPS, но убедись, что твоя страница тоже подается по HTTPS.
  • Добавь защиту от спама. Скрытое поле-ловушка или интеграция CAPTCHA значительно сокращает мусорные заявки. For a deeper look at this topic, see our guide on лучшие практики защиты форм от спама.
  • Тестируй путь ошибки намеренно. Временно измени URL endpoint на что-то недействительное и убедись, что твое сообщение об ошибке появляется. Большинство разработчиков тестируют только успешный путь.
  • Держи URL endpoint вне системы контроля версий. Если твой проект с открытым исходным кодом, храни Sendform endpoint в переменной окружения или конфигурационном файле, который указан в .gitignore.

Для пользователей статических сайтов: Если твой проект — это Hugo, Eleventy или обычный HTML сайт без сервера, описанный здесь подход с fetch() является рекомендуемым методом. Читай больше в нашем руководстве по серверной обработке форм для статических сайтов.

Заключение

Замена стандартной отправки формы на вызов fetch() — это одно из самых эффектных улучшений, которые ты можешь сделать для любой контактной формы или формы захвата лидов. Результат — более быстрый, профессиональный опыт, который удерживает пользователей на твоей странице и дает тебе полный контроль над сообщениями обратной связи. Сочетай это с Sendform endpoint и ты полностью исключаешь необходимость в серверном коде. Твоя форма работает, заявки попадают в твой почтовый ящик, а пользователи никогда не видят раздражающую перезагрузку страницы. Создай свой бесплатный Sendform endpoint сегодня и получи первую заявку за считанные минуты.

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

Да. Поскольку fetch() работает полностью в браузере, он функционирует на статических HTML сайтах, JAMstack проектах и любой платформе, которая подает HTML. Тебе не нужен собственный сервер. Единственное требование — это endpoint (как URL Sendform), который может принимать POST запрос.

fetch() — это современная замена XMLHttpRequest. Он использует Promises, поддерживает async/await и имеет более чистый API. Для новых проектов всегда предпочтителен fetch(). Оба достигают одного результата ajax отправки формы, но fetch() требует значительно меньше шаблонного кода.

Нет. Когда ты передаешь объект FormData как body, браузер автоматически устанавливает Content-Type в multipart/form-data и включает правильную строку границы. Ручная установка фактически сломает запрос, пропустив это значение границы.

Зарегистрируйся на Sendform, создай новую форму в панели управления и скопируй сгенерированный URL endpoint. Вставь этот URL как цель в твой вызов fetch(). Заявки будут немедленно пересланы на твой настроенный email адрес.

Сетевая ошибка заставляет Promise fetch() отклониться, что ловится внешним блоком try/catch в примере кода. Пользователь видит сообщение "Ошибка сети", которое ты определил. Отправка не ставится в очередь автоматически; пользователь должен попробовать снова, когда соединение восстановится.