Fetch API в JavaScript: делаем HTTP‑запросы и обрабатываем ответы (JavaScript)

Fetch API — это встроенный в браузер способ делать HTTP‑запросы. Не нужно подключать библиотеки: просто вызываешь fetch(), передаёшь URL и (опционально) настройки, получаешь промис с ответом. Дальше разбираешь тело ответа (JSON, текст, Blob и т. д.) и работаешь с данными.


Минимальный GET‑запрос

Самый простой запрос:

js
fetch('https://api.example.com/data')
  .then(response => {
    if (!response.ok) {
      throw new Error(`Ошибка HTTP: ${response.status}`);
    }
    return response.json(); // читаем тело как JSON
  })
  .then(data => console.log(data))
  .catch(err => console.error('Ошибка:', err));

Что тут важно:

  • response.ok — это true, если статус в диапазоне 200–299. Если нет — значит, сервер вернул ошибку (404, 500 и т. п.), и её надо обработать.
  • response.json() — асинхронный метод, который читает поток ответа и парсит JSON. Он тоже возвращает промис.
  • .catch() ловит и сетевые ошибки (нет сети, таймаут), и ошибки, которые ты сам выбросил (например, при !response.ok).

GET с параметрами (query string)

Если нужны параметры (например, ?page=1&limit=10), лучше собирать их через URLSearchParams:

js

<

const params = new URLSearchParams({
  page: '1',
  limit: '10',
  search: 'hello'
});
 
fetch(`https://api.example.com/items?${params}`)
  .then(r => {
    if (!r.ok) throw new Error(`HTTP ${r.status}`);
    return r.json();
  })
  .then(data => console.log(data))
  .catch(console.error);

Так меньше шансов ошибиться в ручном склеивании строки.


POST с JSON‑телом

Для отправки данных чаще всего используют JSON:

js
const payload = { name: 'Alice', age: 30 };
 
fetch('https://api.example.com/users', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify(payload)
})
  .then(r => {
    if (!r.ok) throw new Error(`HTTP ${r.status}`);
    return r.json();
  })
  .then(data => console.log('Создан пользователь:', data))
  .catch(console.error);

Важные моменты:

  • Обязательно указываем Content-Type: application/json.
  • Тело запроса (body) должно быть строкой — поэтому JSON.stringify.
  • Сервер должен уметь принимать JSON и возвращать понятный ответ.

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

fetch не читает тело автоматически. Ты сам выбираешь, как его читать:

  • response.text() — обычный текст.
  • response.json() — JSON (самый частый случай).
  • response.blob() — бинарные данные (картинки, файлы).
  • response.arrayBuffer() — низкоуровневые бинарные данные.

Пример с текстом:

js
fetch('https://example.com/page.html')
  .then(r => r.text())
  .then(html => console.log(html))
  .catch(console.error);

Пример с картинкой (Blob → URL):

js
fetch('https://example.com/image.png')
  .then(r => r.blob())
  .then(blob => {
    const url = URL.createObjectURL(blob);
    document.querySelector('img').src = url;
  })
  .catch(console.error);

async/await: более читаемый стиль

Вместо цепочки .then() можно писать через async/await:

js
async function getData() {
  try {
    const response = await fetch('https://api.example.com/data');
 
    if (!response.ok) {
      throw new Error(`HTTP ${response.status}`);
    }
 
    const data = await response.json();
    console.log(data);
  } catch (err) {
    console.error('Ошибка запроса:', err);
  }
}
 
getData();

Это тот же самый код, но читается линейно: сначала запрос, потом проверка, потом разбор данных, потом обработка ошибок.


Частые ошибки и где «ломается»

  1. Забыли проверить response.ok
    Fetch считает успешным любой ответ от сервера, даже 404 и 500. Если не проверить ok, ты получишь промис, который «успешен», но внутри — ошибка сервера.
  2. Пытаются сразу использовать данные без await или .then()
    response.json() возвращает промис. Нельзя написать const data = response.json(); и сразу использовать data. Нужно либо await response.json(), либо .then(json => ...).
  3. Неправильный Content-Type или забыли JSON.stringify
    Если отправить JSON без заголовка Content-Type: application/json, сервер может не понять формат. Если забыть stringify, тело уйдёт как [object Object] — сервер не сможет распарсить.
  4. CORS‑ошибки
    Если делаешь запрос на другой домен, а сервер не разрешает CORS, браузер заблокирует ответ. Это видно в консоли как CORS‑ошибка. Тут проблема на стороне сервера: он должен отдавать правильные заголовки.
  5. Нет обработки сетевых ошибок
    Сетевые ошибки (нет интернета, таймаут, DNS) попадают только в .catch() или в try/catch при await. Если не ловить — ошибка просто «провалится» и ничего не будет видно.

Пример: форма отправки данных с обработкой ошибок

Допустим, есть простая форма:

html
<form id="userForm">
  <input name="name" placeholder="Имя" required>
  <button type="submit">Отправить</button>
</form>
<div id="message"></div>

JS:

document.getElementById('userForm').addEventListener('submit', async (e) => {
  e.preventDefault();
  const form = e.target;
  const messageBox = document.getElementById('message');
  messageBox.textContent = '';
 
  const data = {
    name: form.name.value.trim()
  };
 
  try {
    const res = await fetch('/api/users', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(data)
    });
 
    if (!res.ok) {
      const errData = await res.json().catch(() => ({}));
      throw new Error(errData.message || `Ошибка сервера: ${res.status}`);
    }
 
    const result = await res.json();
    messageBox.textContent = 'Пользователь создан: ' + result.name;
  } catch (err) {
    messageBox.textContent = 'Ошибка: ' + err.message;
  }
});

Здесь:

  • Отменяем стандартное поведение формы (preventDefault).
  • Собираем данные, отправляем JSON.
  • Проверяем ok, читаем ошибку из тела, если она есть.
  • Показываем понятное сообщение пользователю.

Практический совет для PunBB и подобных проектов

Если ты интегрируешь PunBB с внешними сервисами (например, с Яндексом) и делаешь запросы из фронтенда:

  • Держи URL API в конфиге или через прокси на бэкенде, чтобы не светить ключи и не зависеть от CORS.
  • Для аутентификации часто используют куки или заголовки (например, Authorization: Bearer ...). Куки отправляются автоматически, если credentials: 'include' и сервер правильно настроен.
  • Пример с куками:
js
fetch('https://api.example.com/profile', {
  credentials: 'include' // отправлять куки домена
})
.then(r => r.json())
.catch(console.error);

Без credentials: 'include' куки не уйдут — и авторизация не сработает.

Добавить комментарий