Запросы к серверу: fetch
Сайты постоянно обмениваются данными с сервером: загружают товары, отправляют комментарии, проверяют логин. В браузере для этого есть функция fetch(). Она отправляет HTTP-запрос — сообщение серверу по адресу (URL) — и возвращает промис с ответом.
Песочница этого сайта не имеет доступа к сети, поэтому примеры с fetch() здесь не запускаются. Объект ответа можно создать вручную — так мы и потренируемся.
Первый запрос
fetch() принимает адрес и возвращает промис. Дождавшись его через await, получаем объект ответа:
const response = await fetch('https://api.example.com/users/1');
console.log(response.status); // 200Запрос без дополнительных настроек называется GET — он просит сервер отдать данные.
Объект ответа
Ответ сервера — объект класса Response. Его можно создать и вручную, без сети: первым аргументом передают тело ответа, вторым — настройки:
const response = new Response('Привет', { status: 200 });
console.log(response.status); // 200
console.log(response.ok); // truestatus — код ответа: 200 значит «успешно», 404 — «не найдено», 500 — «ошибка сервера». ok равно true для кодов от 200 до 299.
Чтение JSON
Чаще всего сервер присылает данные в формате JSON. Метод json() превращает тело ответа в объект. Он тоже асинхронный, поэтому перед ним нужен await:
const response = new Response('{"name": "Анна", "age": 28}');
const user = await response.json();
console.log(user.name); // АннаДля обычного текста есть метод text(). Тело ответа можно прочитать только один раз.
Проверка статуса
fetch() отклоняет промис только при сбое сети. Ответ 404 или 500 считается успешно полученным, поэтому статус проверяют сами:
async function loadUser(id) {
const response = await fetch(`https://api.example.com/users/${id}`);
if (!response.ok) {
throw new Error(`Ошибка ${response.status}`);
}
return response.json();
}Отправка данных
Чтобы отправить данные, вторым аргументом передают настройки: метод POST, заголовок с типом данных и само тело запроса в виде JSON-строки:
const response = await fetch('https://api.example.com/comments', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ author: 'Олег', text: 'Отличная статья!' }),
});Заголовок Content-Type сообщает серверу, что в теле лежит JSON.
Обработка ошибок
Запрос может не удаться: пропал интернет, сервер недоступен, вернулся код ошибки. Весь запрос оборачивают в try...catch, чтобы показать пользователю понятное сообщение:
try {
const response = await fetch('https://api.example.com/users/7');
if (!response.ok) {
throw new Error(`Ошибка ${response.status}`);
}
const user = await response.json();
console.log(user.name);
} catch (error) {
console.log(`Не удалось загрузить: ${error.message}`);
}Частая ошибка
Забыть await перед response.json(). Метод возвращает промис, а у промиса нет поля name:
const response = new Response('{"name": "Анна"}');
const user = response.json();
console.log(user.name); // undefinedПравильно: const user = await response.json(). Перед fetch() и перед json() нужен свой await.