HTTP-запросы через fetch
Сервер не только отвечает на запросы, но и сам их отправляет: получает курс валют, проверяет адрес через внешний сервис, публикует уведомление. В Node.js для этого есть та же функция fetch(), что и в браузере, — устанавливать ничего не нужно. Как она работает, вы знаете из учебника; здесь — особенности серверного кода.
GET-запрос
Создайте файл scripts/check-blog.js, который запрашивает список статей вашего блога. Сервер из прошлых уроков должен быть запущен в другом окне терминала:
// scripts/check-blog.js
const response = await fetch('http://localhost:3000/posts');
const posts = await response.json();
console.log(`Статей в блоге: ${posts.length}`);node scripts/check-blog.js выведет число статей. await работает прямо в модуле, а response.json() разбирает тело ответа.
Проверка статуса
fetch() не бросает ошибку на ответы 404 или 500 — он бросает её только когда сервер вообще недоступен. Статус проверяют сами через response.ok:
// scripts/check-blog.js
const response = await fetch('http://localhost:3000/posts/999');
if (!response.ok) {
console.log(`Ошибка: ${response.status}`);
} else {
console.log(await response.json());
}Статьи 999 нет, поэтому выведется «Ошибка: 404». response.ok равен true для кодов от 200 до 299.
Отправка JSON
Для POST-запроса указывают метод, заголовок и тело-строку:
// scripts/add-post.js
const response = await fetch('http://localhost:3000/posts', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ title: 'Статья из скрипта', body: 'Отправлено через fetch' }),
});
const post = await response.json();
console.log(response.status, post.id);Выведется 201 и номер новой статьи — тот же результат, что и у curl из прошлого урока.
Ограничение времени
Если внешний сервер завис, fetch() будет ждать очень долго. AbortSignal.timeout() прерывает запрос через указанное число миллисекунд:
// scripts/check-blog.js
try {
const response = await fetch('http://localhost:3000/posts', {
signal: AbortSignal.timeout(3000),
});
console.log(response.status);
} catch (error) {
console.log(`Сервер не ответил: ${error.name}`);
}Если ответа нет три секунды, выведется «Сервер не ответил: TimeoutError». Если сервер не запущен, ошибка тоже попадёт в catch — с именем TypeError и сообщением fetch failed.
Что возвращает ответ
| Свойство или метод | Что даёт |
|---|---|
response.status | Код состояния |
response.ok | true для кодов 200–299 |
response.headers.get(name) | Значение заголовка |
await response.json() | Тело, разобранное как JSON |
await response.text() | Тело как строка |
Частая ошибка
В браузере можно писать fetch('/posts'), потому что адрес достраивается от текущей страницы. В Node.js страницы нет, и относительный адрес вызовет ошибку:
TypeError: Failed to parse URL from /postsВсегда передавайте полный адрес с протоколом и хостом: http://localhost:3000/posts. Базовый адрес удобно хранить в переменной окружения.