Fetch API
fetch(url) просит браузер отправить HTTP-запрос. Сразу возвращается промис, который обычно исполняется объектом Response, а не разобранным JSON.
Сначала Response, затем данные
await fetch(...) даёт статус, заголовки и поток тела. response.json() читает текст, разбирает JSON и возвращает другой промис с данными JavaScript.
Два отдельных этапа
Отделяйте получение ответа от разбора. Полезный статус может быть и у ответа, тело которого не является JSON.
📊 От запроса к данным
| Выражение | Результат | Значение |
|---|---|---|
| fetch(url) | Promise<Response> | запрос начат |
| await fetch(url) | Response | статус, заголовки и поток тела |
| response.json() | Promise<any> | чтение и разбор тела |
| await response.json() | данные JavaScript | разобранный объект или значение |
fetch возвращает промис
Автономный пример использует Blob URL только для показа типа. Это ресурс в памяти браузера, а не одноисточниковый HTTP-адрес.
const blob = new Blob(['{"drink":"lida tea"}'], { type: "application/json" });
const url = URL.createObjectURL(blob);
const ticket = fetch(url);
console.log(ticket instanceof Promise);
ticket.finally(() => URL.revokeObjectURL(url));
Выводится true. В приложении замените Blob URL на HTTP-путь, например /data/drink.json.
Ожидание Response и JSON
Следующий пример создаёт тот же локальный ресурс и выполняет оба ожидания.
async function loadDrink() {
const blob = new Blob(['{"drink":"lida tea"}'], { type: "application/json" });
const url = URL.createObjectURL(blob);
try {
const response = await fetch(url);
if (!response.ok) throw new Error("HTTP " + response.status);
const data = await response.json();
console.log(data.drink);
} finally {
URL.revokeObjectURL(url);
}
}
loadDrink();
Выводится lida tea. Настоящий /data/drink.json мог бы содержать {"drink":"lida tea"}, а чтение осталось бы тем же.
Явная проверка ошибок HTTP
При статусе 404 или 500 fetch обычно всё равно исполняется. Сбой сети может отклонить промис, плохой статус сам по себе — обычно нет. Проверяйте response.ok или response.status.
const response = new Response("Not found", {
status: 404,
statusText: "Not Found"
});
console.log(response.ok);
console.log(response.status);
Созданный ответ выводит false и 404 — именно эти свойства проверяют после настоящего fetch. Не разбирайте страницу ошибки как JSON без гарантии API.
json тоже возвращает промис
json() асинхронно читает и разбирает тело.
const response = new Response('{"drink":"lida tea"}', {
headers: { "Content-Type": "application/json" }
});
const dataPromise = response.json();
console.log(dataPromise instanceof Promise);
dataPromise.then(data => console.log(data.drink));
Выводится true. После await response.json() переменная data содержит объект JavaScript, а data.drink — строку.
Демонстрация без зависимости от адреса
Страница загружает Blob URL и работает автономно. Она показывает процесс и статус 200, но не выдаёт его за запрос к серверу.
<!DOCTYPE html>
<html>
<body>
<p id="cup">blank</p>
<p id="line">…</p>
<script>
async function load() {
const blob = new Blob(['{"drink":"lida tea"}'], { type: "application/json" });
const url = URL.createObjectURL(blob);
try {
const response = await fetch(url);
if (!response.ok) throw new Error("HTTP " + response.status);
const data = await response.json();
document.getElementById("cup").textContent = data.drink;
document.getElementById("line").textContent =
response.status + " / " + data.drink;
} finally {
URL.revokeObjectURL(url);
}
}
load();
</script>
</body>
</html>
Страница показывает 200 / lida tea. В рабочем приложении используйте HTTP URL и проверяйте ok до разбора.
Попробуйте
Создайте /data/drink.json на локальном сервере и замените Blob URL. Затем запросите отсутствующий путь и сравните ok и status.
Частые ошибки
Не принимайте промис от fetch за данные. Не забывайте вызвать и ожидать json(). Не полагайтесь на catch для каждого 404.
Запомните
fetch отправляет запрос и даёт промис Response. Проверьте ok, затем разберите ожидаемое тело. response.json() возвращает промис данных.
🧠 Проверьте Свои Знания
Проверьте Свои Знания
Бросьте себе вызов с помощью этой интерактивной викторины и узнайте, насколько хорошо вы понимаете тему
📝 Инструкции
- Внимательно прочитайте каждый вопрос
- Выберите лучший ответ на каждый вопрос
- Вы можете пересдавать тест столько раз, сколько захотите
- Ваш прогресс будет показан вверху