Современные веб-приложения постоянно общаются с сервером: загружают данные, отправляют формы, обновляют контент без перезагрузки страницы. За это отвечает асинхронный JavaScript. Долгое время стандартом был XMLHttpRequest, но он громоздкий и неудобный. На смену пришёл Fetch API — простой и мощный инструмент для сетевых запросов. В этой статье разберём, как пользоваться Fetch, обрабатывать ответы, ловить ошибки и применять продвинутые приёмы.
Что такое Fetch API и зачем он нужен
Fetch API — это встроенный в браузер интерфейс для выполнения HTTP-запросов. Он основан на промисах, что делает код чище и позволяет избежать ада колбэков. Синтаксис прост: вызываем fetch(url) и получаем промис, который разрешается объектом Response.
В отличие от XMLHttpRequest, Fetch не требует создания экземпляра, настройки обработчиков и вызова send. Всё лаконично:
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Ошибка:', error));
Но это только верхушка айсберга. Fetch умеет гораздо больше: настраивать заголовки, отправлять данные, работать с разными форматами, отменять запросы.
Основы: как выполнить GET-запрос
Самый простой случай — получить данные с сервера. Допустим, у нас есть API, возвращающее список пользователей.
fetch('https://jsonplaceholder.typicode.com/users')
.then(response => {
if (!response.ok) {
throw new Error('Сеть ответила с ошибкой: ' + response.status);
}
return response.json();
})
.then(users => {
users.forEach(user => console.log(user.name));
})
.catch(error => console.error('Ошибка запроса:', error));
Здесь мы проверяем свойство response.ok — оно истинно, если статус ответа в диапазоне 200-299. Если нет — выбрасываем исключение, которое попадёт в catch. Без этой проверки fetch не считает ошибкой статусы 404 или 500, и мы можем пытаться распарсить невалидный JSON.
Метод response.json() читает тело ответа и преобразует его из JSON в JavaScript-объект. Это асинхронная операция, возвращающая промис.
response.ok перед обработкой данных. Fetch не отклоняет промис при HTTP-ошибках, поэтому легко пропустить проблему.
Отправка данных: POST, PUT, DELETE
Для отправки данных используется второй аргумент fetch — объект с настройками. В нём указываем метод, заголовки и тело запроса.
const newUser = {
name: 'Иван',
email: 'ivan@example.com'
};
fetch('https://jsonplaceholder.typicode.com/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json;charset=utf-8'
},
body: JSON.stringify(newUser)
})
.then(response => response.json())
.then(data => console.log('Успех:', data))
.catch(error => console.error('Ошибка:', error));
Обратите внимание: тело запроса должно быть строкой. Если отправляем JSON, используем JSON.stringify и устанавливаем заголовок Content-Type: application/json.
Для PUT и DELETE принцип тот же, меняется только метод. DELETE обычно не требует тела.
| Метод | Назначение | Тело запроса |
|---|---|---|
| GET | Получить данные | Нет |
| POST | Создать ресурс | Да |
| PUT | Обновить ресурс | Да |
| DELETE | Удалить ресурс | Обычно нет |
Обработка ошибок и асинхронный / await
Промисы удобны, но цепочки .then() могут разрастаться. С появлением async/await код стал ещё читаемее. Fetch отлично с ними сочетается.
async function fetchUsers() {
try {
const response = await fetch('https://jsonplaceholder.typicode.com/users');
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const users = await response.json();
console.log(users);
} catch (error) {
console.error('Ошибка при загрузке:', error);
}
}
fetchUsers();
Конструкция try/catch позволяет элегантно обрабатывать как сетевые ошибки, так и ошибки парсинга JSON. Не забывайте, что await можно использовать только внутри async-функции.
Fetch также поддерживает отмену запросов через AbortController. Это полезно, если пользователь ушёл со страницы или запрос долго выполняется.
const controller = new AbortController();
const signal = controller.signal;
fetch('https://api.example.com/slow', { signal })
.then(response => response.json())
.catch(error => {
if (error.name === 'AbortError') {
console.log('Запрос отменён');
} else {
console.error('Ошибка:', error);
}
});
// Отменить запрос через 2 секунды
setTimeout(() => controller.abort(), 2000);
Продвинутые приёмы и сравнение с XMLHttpRequest
Fetch API не поддерживает прогресс загрузки (upload progress) напрямую, в отличие от XMLHttpRequest. Для отслеживания прогресса отправки файлов приходится использовать другие подходы или библиотеки. Также fetch не отправляет куки по умолчанию для кросс-доменных запросов — нужно указывать credentials: 'include'.
Сравним два подхода в таблице:
| Критерий | Fetch API | XMLHttpRequest |
|---|---|---|
| Синтаксис | Простой, на промисах | Громоздкий, на колбэках |
| Поддержка прогресса | Нет (только через ReadableStream) | Есть |
| Отмена запроса | AbortController | abort() |
| Куки по умолчанию | Не отправляются | Отправляются |
Несмотря на некоторые ограничения, Fetch стал стандартом де-факто для сетевых запросов в современном JavaScript. Он лаконичен, мощен и хорошо сочетается с async/await.
Ещё один полезный приём — создание обёртки для fetch, которая автоматически добавляет заголовки, обрабатывает ошибки и возвращает JSON. Это избавит от дублирования кода.
async function request(url, options = {}) {
const defaultHeaders = { 'Content-Type': 'application/json' };
const config = {
...options,
headers: { ...defaultHeaders, ...options.headers }
};
const response = await fetch(url, config);
if (!response.ok) {
const error = await response.json().catch(() => ({}));
throw new Error(error.message || `HTTP ${response.status}`);
}
return response.json();
}
// Использование
request('/api/users')
.then(users => console.log(users))
.catch(err => console.error(err));
Что в итоге
Fetch API — это современный, удобный и мощный инструмент для асинхронных запросов к серверу. Он основан на промисах, легко читается и отлично работает с async/await. Главное — не забывать проверять статус ответа и обрабатывать ошибки. Используйте AbortController для отмены запросов, создавайте обёртки для повторяющихся действий. Тогда ваш код будет чистым и надёжным.
Практикуйтесь, экспериментируйте с разными методами и форматами. Fetch — это навык, который пригодится в любом веб-проекте.



