Fetch API представляет собой современный интерфейс
браузерного JavaScript для выполнения HTTP-запросов. Он заменяет
устаревший XMLHttpRequest и обеспечивает более гибкую,
цепочечную и читаемую модель работы с сетевыми запросами.
Ключевая особенность fetch заключается в том, что он
основан на Promise, что позволяет использовать его вместе с
async/await и строить асинхронный код без вложенных
колбэков.
Базовый синтаксис:
fetch(url, options)
url — адрес ресурсаoptions — объект конфигурации запроса (необязательный
параметр)Самый распространённый сценарий использования — получение данных с сервера.
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => {
console.log(data);
})
.catch(error => {
console.error('Ошибка запроса:', error);
});
Важный момент: fetch не отклоняет Promise
при HTTP-ошибках (например, 404 или 500). Он завершает запрос успешно, и
проверка статуса выполняется вручную.
Результатом выполнения fetch является объект
Response, который содержит:
status — HTTP-код ответа
ok — булево значение успешности (true для
200–299)
headers — заголовки ответа
методы для получения тела ответа:
json()text()blob()formData()arrayBuffer()Пример проверки статуса:
fetch('/api/user')
.then(response => {
if (!response.ok) {
throw new Error(`HTTP ошибка: ${response.status}`);
}
return response.json();
})
.then(user => console.log(user))
.catch(err => console.error(err));
Современный способ работы с fetch строится на
async/await, что делает код линейным и читаемым.
async function getData() {
try {
const response = await fetch('/api/data');
if (!response.ok) {
throw new Error(`Ошибка: ${response.status}`);
}
const data = await response.json();
console.log(data);
} catch (error) {
console.error('Ошибка загрузки:', error);
}
}
GET-запросы часто используют строку запроса:
fetch('/api/search?query=leaflet&limit=10')
.then(res => res.json())
.then(data => console.log(data));
Для динамического формирования параметров удобно использовать
URLSearchParams:
const params = new URLSearchParams({
query: 'leaflet',
limit: 10
});
fetch(`/api/search?${params.toString()}`)
.then(res => res.json())
.then(data => console.log(data));
Для отправки данных используется параметр options.
fetch('/api/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'Ivan',
age: 30
})
})
.then(res => res.json())
.then(data => console.log(data));
Ключевые элементы:
method — HTTP-методheaders — заголовки запросаbody — тело запроса (строка, FormData и т.д.)Объект Headers позволяет управлять HTTP-заголовками:
const headers = new Headers();
headers.append('Authorization', 'Bearer token123');
headers.append('Accept', 'application/json');
fetch('/api/private', {
headers
});
Также можно передавать объект:
fetch('/api/private', {
headers: {
Authorization: 'Bearer token123'
}
});
FormData используется для отправки форм и файлов:
const formData = new FormData();
formData.append('username', 'Ivan');
formData.append('avatar', fileInput.files[0]);
fetch('/api/upload', {
method: 'POST',
body: formData
});
Важно: при использовании FormData заголовок
Content-Type устанавливается автоматически.
const data = await response.json();
const text = await response.text();
const blob = await response.blob();
const url = URL.createObjectURL(blob);
const buffer = await response.arrayBuffer();
Тело ответа можно прочитать только один раз. Для повторного
использования применяется clone():
const responseClone = response.clone();
const data1 = await response.json();
const data2 = await responseClone.json();
Fetch API не поддерживает таймаут напрямую, но его можно
реализовать через AbortController.
const controller = new AbortController();
const timeout = setTimeout(() => {
controller.abort();
}, 5000);
try {
const response = await fetch('/api/data', {
signal: controller.signal
});
clearTimeout(timeout);
const data = await response.json();
console.log(data);
} catch (err) {
if (err.name === 'AbortError') {
console.log('Запрос прерван по таймауту');
}
}
Для нестабильных сетей используется повтор выполнения запроса:
async function fetchWithRetry(url, retries = 3) {
for (let i = 0; i < retries; i++) {
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error('Ошибка HTTP');
}
return await response.json();
} catch (e) {
if (i === retries - 1) throw e;
}
}
}
Браузер может кэшировать запросы, а поведение управляется через
cache:
fetch('/api/data', {
cache: 'no-cache'
});
Возможные значения:
defaultno-storereloadno-cacheforce-cacheonly-if-cachedFetch API подчиняется политике CORS (Cross-Origin
Resource Sharing). Запросы на другой домен требуют разрешения со стороны
сервера.
Типичные ошибки:
Access-Control-Allow-OriginOPTIONSДля отправки cookies и авторизационных данных:
fetch('/api/profile', {
credentials: 'include'
});
Варианты:
same-origin (по умолчанию)includeomitНесколько запросов можно выполнять одновременно через
Promise.all:
const [users, posts] = await Promise.all([
fetch('/api/users').then(r => r.json()),
fetch('/api/posts').then(r => r.json())
]);
fetch не ловит HTTP-ошибки автоматически, но ловит
сетевые сбои:
fetch('/api/data')
.then(res => {
if (!res.ok) throw new Error('HTTP error');
return res.json();
})
.catch(err => {
console.error('Сетевая ошибка или сбой:', err);
});
В прикладных интерфейсах Fetch API часто абстрагируется
в сервисный слой:
const api = {
async getUsers() {
const res = await fetch('/api/users');
if (!res.ok) throw new Error('Ошибка загрузки пользователей');
return res.json();
},
async createUser(data) {
const res = await fetch('/api/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
});
if (!res.ok) throw new Error('Ошибка создания пользователя');
return res.json();
}
};
Несмотря на гибкость, имеются особенности:
fetch использует Promise,
XMLHttpRequest — колбэкиfetch имеет более чистый синтаксисfetch не поддерживает прогресс загрузки из коробкиfetch не прерывает запрос при HTTP-ошибках
автоматическиВ клиентских приложениях Fetch API становится базовым
слоем взаимодействия с сервером. Поверх него строятся:
Типичная архитектура:
UI слой → сервис API → fetch → сервер
Такой подход позволяет изолировать сетевую логику от компонентов интерфейса и повысить тестируемость кода.