AJAX и Fetch API

AJAX — подход, при котором клиент обменивается данными с сервером без полной перезагрузки страницы. Название исторически содержит XML, но сегодня ответ чаще передаётся как JSON.

fetch() — браузерный Promise-based API для HTTP-запросов.

GET

async function loadItem(id, signal) {
  const response = await fetch(
    `/api/items/${encodeURIComponent(id)}`,
    {
      headers: { Accept: "application/json" },
      signal
    }
  );
 
  if (!response.ok) {
    throw new Error(`Request failed: ${response.status}`);
  }
 
  return response.json();
}

Проверка response.ok обязательна: fetch отклоняет Promise при сетевой ошибке, но HTTP 404 или 500 возвращаются как обычный Response.

POST JSON

async function createItem(command) {
  const response = await fetch("/api/items", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Accept: "application/json"
    },
    body: JSON.stringify(command)
  });
 
  if (!response.ok) {
    const problem = await response.json();
    throw new Error(problem.message ?? "Unknown API error");
  }
 
  return response.json();
}

Отмена и timeout

Сам fetch не принимает параметр timeout. Запрос отменяется через AbortController:

const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), 5_000);
 
try {
  await loadItem("42", controller.signal);
} finally {
  clearTimeout(timer);
}

Отмена ожидания на клиенте не гарантирует, что backend прекратил уже начатую операцию.

Частые ошибки

  • не проверить HTTP status;
  • повторить неидемпотентный запрос после timeout;
  • забыть URL-encoding;
  • считать CORS ошибкой backend-бизнес-логики;
  • отправить Content-Type, не соответствующий body;
  • обновить UI ответом старого запроса после нового;
  • логировать token или персональные данные;
  • запускать N отдельных запросов вместо batch API.

Последняя проблема разобрана в Кейс сетевой N plus 1.

Вопросы для собеседования

Чем AJAX отличается от Fetch?

AJAX — общий подход, Fetch — конкретный API.

Отправляет ли fetch cookies?

Для same-origin — в соответствии с credentials policy. Для cross-origin поведение задаётся credentials и ограничивается CORS/SameSite.

Что произойдёт при невалидном JSON?

response.json() вернёт rejected Promise, даже если HTTP status успешный.

Связанные заметки