Fetch API #
Fetch — современный способ отправить HTTP-запрос из браузера и получить Response. Метод возвращает Promise, поэтому его удобно сочетать с async/await.
Простой GET-запрос #
const response = await fetch('/api/tracks?limit=5')
const tracks = await response.json()
console.log(tracks.length)
По умолчанию fetch делает GET без тела. URL может быть относительным (/api/...) — браузер подставит origin текущей страницы.
Если сервер отвечает не JSON, а текстом или файлом:
const response = await fetch('/api/export.csv')
const csv = await response.text()
Разбор JSON #
response.json() тоже возвращает Promise: тело читается асинхронно.
async function loadPlaylist(id) {
const response = await fetch(`/api/playlists/${id}`)
if (!response.ok) {
throw new Error(`HTTP ${response.status}`)
}
return response.json()
}
const playlist = await loadPlaylist('focus-tracks')
console.log(playlist.title)
Важно: fetch не бросает ошибку при статусе 404 или 500 — Promise отклоняется только при сбое сети. Код ответа нужно проверять вручную через response.ok или response.status.
response.ok и response.status #
| Свойство | Значение |
|---|---|
status | Числовой код: 200, 404, 500 |
ok | true, если статус в диапазоне 200–299 |
statusText | Текстовая фраза, например «Not Found» |
const response = await fetch('/api/orders/999')
console.log(response.status) // 404
console.log(response.ok) // false
if (!response.ok) {
const message = await response.text()
console.error('Ошибка:', message)
}
Паттерн «проверить ok, затем парсить тело» защищает от попытки вызвать .json() на HTML-странице ошибки.
Заголовки #
Заголовки передают метаданные: тип контента, авторизацию, язык.
const response = await fetch('/api/cart', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
},
body: JSON.stringify({ sku: 'kb-01', qty: 1 }),
})
Request headers — то, что клиент отправляет. Response headers читаются из объекта response.headers:
const type = response.headers.get('content-type')
if (type?.includes('application/json')) {
const data = await response.json()
}
Некоторые заголовки браузер выставляет сам (например, User-Agent) или блокирует из JS по правилам безопасности — подробнее в статье про CORS.
POST и другие методы #
await fetch('/api/feedback', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ rating: 5, comment: 'Понятные примеры' }),
})
Для форм и загрузки файлов используют FormData вместо JSON — тело запроса браузер сформирует с нужным Content-Type.
Частые ошибки #
- Не проверили
response.ok— парсите JSON от ошибки сервера и получаетеSyntaxError. - Дважды читаете тело — поток можно прочитать только один раз; сохраните результат в переменную.
- Забыли
await— в переменной лежит Promise, а не данные. - CORS — запрос ушёл, но браузер скрыл ответ; см. CORS и ошибки запросов.
// плохо: тело прочитано дважды
const response = await fetch('/api/user')
const user = await response.json()
const copy = await response.json() // TypeError
// хорошо
const response = await fetch('/api/user')
const user = await response.json()
processUser(user)
Итог #
fetch(url)возвращает Promise с объектомResponse.- Для JSON:
await response.json()после проверкиresponse.ok. - Статусы 4xx/5xx не отклоняют Promise
fetch— проверяйтеokилиstatus. - Заголовки задаются в объекте
headers; ответные — черезresponse.headers.get(). - POST и другие методы настраиваются полем
methodиbody.