«Хороший сайт делается для людей, а поисковики приходят следом»

— из принципов редакции SeoLiga.ru
Главная » Статьи » Веб-программирование » AJAX: обмен данными без перезагрузки страницы

AJAX: обмен данными без перезагрузки страницы

Раньше любое действие на сайте означало перезагрузку страницы целиком: нажал кнопку — подожди, пока браузер получит новую страницу и отрисует всё заново. AJAX изменил подход. Страница остаётся на месте, а данные подгружаются в фоне и вставляются в нужное место. Так работают динамические списки, поиск с подсказками, лайки, формы без перехода и бесконечная лента. Давайте разберёмся, как это устроено и как использовать технологию без неприятных сюрпризов.

Что означает AJAX

Название расшифровывается как асинхронный JavaScript и XML. Сегодня XML используется редко, чаще передают JSON, но суть не поменялась. Скрипт на странице отправляет запрос серверу, не блокируя интерфейс, получает ответ и обновляет только нужную часть документа. Ключевое слово здесь «асинхронный»: пользователь продолжает работать, пока данные в пути.

Преимущества подхода очевидны:

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

Классика: XMLHttpRequest

Исторически первым инструментом был объект XMLHttpRequest. Он работает до сих пор, и знать его полезно, хотя бы чтобы разбираться в старом коде.

var xhr = new XMLHttpRequest();
xhr.open("GET", "/api/news?page=2", true);
xhr.onreadystatechange = function () {
  if (xhr.readyState === 4) {
    if (xhr.status === 200) {
      document.getElementById("list").innerHTML = xhr.responseText;
    } else {
      console.error("Ошибка: " + xhr.status);
    }
  }
};
xhr.send();

Третий параметр true включает асинхронный режим. Состояние запроса проходит несколько стадий, и четвёртая означает, что ответ получен полностью. После этого проверяют код ответа: значение 200 говорит об успехе.

Современный способ: fetch

Функция fetch возвращает промис и делает код заметно чище. Тот же запрос выглядит так:

fetch("/api/news?page=2")
  .then(function (response) {
    if (!response.ok) {
      throw new Error("Статус " + response.status);
    }
    return response.json();
  })
  .then(function (data) {
    renderList(data.items);
  })
  .catch(function (err) {
    console.error(err);
  });

С синтаксисом async/await получается ещё читабельнее:

async function loadNews(page) {
  try {
    const response = await fetch("/api/news?page=" + page);
    if (!response.ok) throw new Error("Статус " + response.status);
    const data = await response.json();
    renderList(data.items);
  } catch (err) {
    showError("Не удалось загрузить новости");
  }
}

Одна особенность, на которой спотыкаются новички: fetch не считает ошибкой ответ с кодом 404 или 500. Промис отклоняется только при сетевой неполадке. Поэтому проверку response.ok нужно делать самому.

Отправка данных на сервер

Чтобы отправить форму без перезагрузки, используют метод POST и передают тело запроса. Данные чаще всего пакуют в JSON:

async function sendComment(text) {
  const response = await fetch("/api/comments", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ text: text })
  });
  return response.json();
}

Если нужно отправить файл или обычную форму целиком, удобен объект FormData. Он сам формирует правильное тело запроса, и заголовок типа содержимого указывать не нужно.

Формат ответа: JSON или готовый HTML

Сервер может возвращать данные двумя способами. Первый — структурированный JSON, из которого скрипт сам строит разметку. Он удобен для приложений и мобильных клиентов, но требует шаблонов на стороне браузера. Второй — готовый фрагмент HTML, который просто вставляется на страницу. Проще в реализации, но жёстче связывает серверную часть с интерфейсом.

Выбор зависит от задачи. Для небольших улучшений обычного сайта подойдёт готовый HTML. Для сложного интерфейса лучше JSON.

Типичные задачи

  1. Подсказки в поиске. При вводе запроса отправляется запрос и показывается список вариантов.
  2. Подгрузка списка. Кнопка «показать ещё» или бесконечная прокрутка.
  3. Проверка формы. Например, занят ли логин, ещё до отправки всей формы.
  4. Голосования и лайки. Изменение счётчика без перехода на другую страницу.
  5. Автообновление. Периодический опрос сервера на предмет свежих данных.

Для подсказок важно не отправлять запрос на каждый символ. Используйте задержку: ждите короткую паузу после последнего нажатия клавиши, и только потом отправляйте. Это снижает нагрузку на сервер и убирает мерцание списка.

Обработка ошибок и состояния загрузки

Сеть ненадёжна, и это нужно учитывать. Хороший интерфейс всегда сообщает о том, что происходит:

  • во время запроса показывает индикатор загрузки;
  • блокирует кнопку, чтобы не отправить форму повторно;
  • при ошибке выводит понятное сообщение и даёт повторить;
  • учитывает таймаут, если сервер молчит слишком долго.

Ещё одна ловушка — «гонка» запросов. Если пользователь быстро печатает, ответ на старый запрос может прийти позже ответа на новый и затереть актуальный результат. Решение: отменять предыдущий запрос или сравнивать порядковый номер ответа.

Безопасность

AJAX не делает сайт ни безопаснее, ни опаснее сам по себе, но требует внимания к нескольким вещам:

  • Валидация на сервере. Проверка в браузере нужна для удобства, а настоящая защита должна быть на сервере. Запрос можно подделать.
  • XSS. Если вставляете пришедший текст в страницу через innerHTML, экранируйте пользовательские данные. Для обычного текста безопаснее textContent.
  • CSRF. Изменяющие запросы должны быть защищены токеном.
  • Ограничение источников. Запросы на другой домен подчиняются правилам CORS; настраивайте разрешённые источники осознанно, а не открывайте всё подряд.

AJAX и поисковая оптимизация

Для SEO динамическая подгрузка — зона риска. Если важный контент появляется только после выполнения скрипта, поисковый робот может не увидеть его или увидеть с задержкой. Практические правила:

  1. Основной контент страницы отдавайте в HTML сразу, а AJAX используйте для дополнительных возможностей.
  2. Для постраничных списков сохраняйте обычные ссылки на страницы, а скрипт лишь улучшает их поведение.
  3. Если меняете содержимое и хотите, чтобы оно имело свой адрес, используйте управление историей браузера, чтобы URL соответствовал состоянию.
  4. Проверяйте, как страницу видит робот, через инструмент просмотра страницы в вебмастерских сервисах.

Принцип прогрессивного улучшения работает здесь отлично: сайт должен функционировать и без скриптов, а скрипты делают его удобнее.

Отладка

В панели разработчика браузера есть вкладка сети, где видны все запросы: адрес, метод, код ответа, заголовки, тело и время. Если что-то не работает, начните с неё. Часто оказывается, что запрос уходит не на тот адрес, возвращается ошибка сервера или ответ пришёл не в ожидаемом формате. Консоль подскажет ошибки скрипта.

Заключение

AJAX — фундаментальный приём современного веба. Он делает интерфейсы живыми, а работу с сайтом комфортной. Предпочитайте fetch, проверяйте статусы ответов, обрабатывайте ошибки и состояния загрузки, не забывайте про безопасность и позаботьтесь, чтобы важный контент оставался доступен поисковым роботам без выполнения скриптов. Тогда динамика пойдёт сайту на пользу, а не создаст скрытые проблемы.

ПО
Павел Орлов
Автор SeoLiga.ru. Пишет о практике: что работает на реальных проектах, а что лучше обойти стороной. Хотите предложить свою статью? Загляните в раздел «Авторам».