Fetch / axios — типовые запросы
Приветствую! Здесь вы наверняка найдете, что ищете. Примеры в лаборатории рассчитаны на то, что мы разбираем что-то конкретное.
Текущая статья посвящена HTTP-запросам на fetch и axios — GET, POST, JSON, токен, FormData и React.
Поэтому за теорией по текущей теме вам — в энциклопедию. Если ещё не погружались, то маршрут прост:
- Основы
- Система и сеть
- Данные и разметка
- Код и разработка
- Языки
- Искусственный интеллект
- Проект
- Инфраструктура и безопасность
- Спин-офф
Обязательно пройдитесь.
А теперь приступим к нашему предмету.
Проверка API в терминале — curl / fetch — API-запросы.
Promise и async/await — асинхронное программирование.
Каркас API-клиента — практика JavaScript.
Отмена запросов — AbortController.
Тот же GET в мобильном приложении — Flutter + FutureBuilder.
Как запустить любой пример
Вариант 1 — консоль браузера (самый быстрый)
- Откройте любой сайт или пустую вкладку.
- Нажмите F12 → вкладка Console.
- Вставьте код с
await— в современных браузерах top-levelawaitв консоли разрешён. - Нажмите Enter. Ответ появится в консоли или во вкладке Network.
Если браузер ругается на await снаружи функции, оберните код:
(async () => {
const res = await fetch('https://jsonplaceholder.typicode.com/posts/1');
console.log(await res.json());
})();
Разбор обёртки:
| Часть | Смысл |
|---|---|
(async () => { .. })() |
Создали анонимную async-функцию и сразу вызвали |
| Зачем | await работает только внутри async-функции |
console.log(await res.json()) |
Печатаем разобранный JSON в консоль |
Вариант 2 — Node.js 18+
- Установите Node.js (LTS).
- Создайте файл
request.mjs(расширение.mjs— чтобы работалimport). - Вставьте пример, сохраните.
- В терминале в папке с файлом:
node request.mjs
Вариант 3 — проект Vite / React
npm create vite@latest my-app→ выберите React или Vanilla.cd my-app && npm install— для axios ещёnpm install axios.- Код fetch/axios — в
useEffect, обработчик кнопки или отдельный файлsrc/api/...
Учебные URL бесплатны: jsonplaceholder.typicode.com, httpbin.org.
Что такое fetch и axios — простыми словами
Сайт в браузере обычно запрашивает у сервера данные по HTTP — как вы открываете страницу, только ответ приходит JSON (текст с { "ключ": "значение" }), а не готовая HTML-страница.
flowchart LR
A[Ваш JS-код] -->|fetch или axios| B[Сервер API]
B -->|статус 200 + JSON| A
A -->|показать на странице| C[DOM / React]
| Слово | Простое объяснение |
|---|---|
| fetch | Встроенная функция браузера и Node.js — «сходи по URL, принеси ответ» |
| axios | Библиотека npm — то же HTTP, но короче код и удобнее ошибки |
| GET | «Дай прочитать» — список постов, профиль пользователя |
| POST | «Прими новые данные» — форма, создание записи |
| JSON | Формат обмена: {"title":"hello","userId":1} |
| Promise | «Обещание результата потом» — поэтому нужен await |
| 401 / 404 | Код ответа: нет доступа / не найдено |
Навигация по примерам
| Ищут в интернете | Раздел ниже |
|---|---|
| javascript fetch example / fetch api пример | Обязательный шаблон fetch |
| fetch get json / как получить json fetch | GET — один пост |
| fetch post json / javascript post request | POST с JSON |
| axios get request example / axios get пример | Обязательный шаблон axios |
| axios post example / axios post json | POST с JSON |
| fetch query parameters / параметры в url | Query-параметры |
| axios bearer token / authorization header | Bearer-токен |
| fetch timeout / abortcontroller fetch | Таймаут |
| axios interceptors / axios create instance | Interceptors |
| react fetch useeffect / загрузка данных react | React useEffect |
| fetch vs axios / чем отличается axios | fetch и axios — когда что |
| failed to fetch cors / cors error | CORS |
| javascript api request localhost | localhost |
Основы — с чего начать
Обязательный шаблон fetch
Любой рабочий GET на fetch строится из трёх шагов:
fetch(url)— отправить запрос.- Проверить
res.ok— убедиться, что сервер не вернул 404/500. await res.json()— прочитать тело как JSON.
Задача: получить заголовок поста с id=1 и вывести в консоль.
const res = await fetch('https://jsonplaceholder.typicode.com/posts/1');
if (!res.ok) {
throw new Error(`HTTP ${res.status} ${res.statusText}`);
}
const data = await res.json();
console.log(data.title);
Разбор построчно:
| Строка | Что происходит | Зачем |
|---|---|---|
const res = await fetch('..') |
Браузер отправляет GET на URL и ждёт ответ | fetch возвращает Promise; await «останавливает» код до ответа |
| URL в кавычках | Адрес ресурса на сервере | /posts/1 — пост с номером 1 |
if (!res.ok) |
Проверка: статус не из диапазона 200–299 | fetch не считает 404 ошибкой JavaScript — только res.ok === false |
throw new Error(..) |
Прерывает выполнение с текстом ошибки | В консоли красное сообщение HTTP 404 Not Found |
`HTTP ${res.status}` |
Шаблонная строка — подставляет число статуса | Удобно для отладки и отчёта |
const data = await res.json() |
Читает тело ответа и парсит JSON → объект JS | Второй await: чтение потока тоже асинхронное |
console.log(data.title) |
Печатает поле title из объекта |
Так данные попадают на экран или в отладку |
Что увидите в консоли (фрагмент):
sunt aut facere repellat provident occaecati excepturi optio reprehenderit
Частая ошибка: забыть await перед res.json() — в переменной окажется Promise, а не объект, и data.title будет undefined.
Попробуйте: URL ../posts/99999 — сработает !res.ok, увидите HTTP 404.
Обязательный шаблон axios
axios — отдельная библиотека. Её ставят через npm, JSON разбирается автоматически, HTTP-ошибки бросают исключение.
Установка (один раз в проекте):
npm install axios
Задача: тот же GET — заголовок поста id=1.
import axios from 'axios';
const { data } = await axios.get('https://jsonplaceholder.typicode.com/posts/1');
console.log(data.title);
Разбор построчно:
| Строка | Что происходит | Зачем |
|---|---|---|
import axios from 'axios' |
Подключает модуль из node_modules |
В браузере через Vite/Webpack; в Node — файл .mjs или "type":"module" |
axios.get(url) |
GET-запрос; внутри — тот же HTTP, что у fetch | Короткая запись вместо fetch + опций |
const { data } = await .. |
Деструктуризация — достаём поле data из ответа axios |
axios всегда кладёт тело ответа в .data |
data.title |
Поле объекта, как у fetch | Структура JSON от сервера та же |
Что увидите: тот же заголовок поста, что и в примере с fetch.
Разница с fetch при ошибке:
try {
await axios.get('https://jsonplaceholder.typicode.com/posts/99999');
} catch (error) {
console.log('Статус:', error.response?.status); // 404
}
| fetch | axios | |
|---|---|---|
| 404 | res.ok === false, код не падает |
catch, error.response.status === 404 |
| JSON | await res.json() вручную |
уже в data |
Попробуйте: запустите блок try/catch выше — увидите статус 404 без ручной проверки ok.
fetch и axios — когда что
| Критерий | fetch | axios |
|---|---|---|
| Установка | Уже есть в браузере и Node 18+ | npm install axios |
| Строк кода на GET | ~5 с проверкой ok |
~2 |
| Ошибка 404/500 | Проверка res.ok |
Автоматически throw |
| Таймаут | AbortController (~10 строк) |
timeout: 5000 |
| Токен на все запросы | Своя функция apiRequest |
interceptors |
| Курсовая / лабораторная | Отлично — без зависимостей | Отлично — меньше boilerplate |
| Большой React-проект | Нужна обёртка | Частый выбор команды |
Для первого знакомства начните с fetch в консоли F12. Когда появится проект с package.json — добавьте axios.
Стартовые запросы
GET — один пост по id
Задача: прочитать один ресурс по номеру — самый частый запрос в учебниках («получить пользователя», «получить товар»).
fetch:
const res = await fetch('https://jsonplaceholder.typicode.com/posts/1');
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const post = await res.json();
console.log(post.id, post.title);
axios:
import axios from 'axios';
const { data: post } = await axios.get('https://jsonplaceholder.typicode.com/posts/1');
console.log(post.id, post.title);
Разбор полей ответа:
| Поле | Пример | Смысл |
|---|---|---|
id |
1 |
Номер записи в базе |
title |
строка | Заголовок поста |
body |
длинный текст | Текст поста |
userId |
1 |
Автор — связь с другим ресурсом /users/1 |
Что увидите в консоли:
1 sunt aut facere repellat provident occaecati excepturi optio reprehenderit
Как проверить в DevTools: F12 → Network → обновите или выполните код → клик по строке posts/1 → вкладки Headers (статус 200) и Response (весь JSON).
Попробуйте: замените 1 на 99999 — fetch: res.ok === false; axios: ошибка в catch.
POST с JSON
Задача: отправить новый объект на сервер — кнопка «Сохранить», форма регистрации, создание заметки.
fetch:
const res = await fetch('https://jsonplaceholder.typicode.com/posts', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
title: 'hello',
body: 'text',
userId: 1,
}),
});
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const created = await res.json();
console.log('Новый id:', created.id);
Разбор построчно (fetch):
| Строка | Что происходит | Зачем |
|---|---|---|
второй аргумент { .. } |
Настройки запроса | Без него fetch делает только GET |
method: 'POST' |
HTTP-метод «создать / отправить» | GET тело обычно не несёт |
headers: { 'Content-Type': 'application/json' } |
Говорим серверу: «в теле JSON» | Без заголовка сервер может не понять формат |
JSON.stringify({..}) |
Объект JS → строка для HTTP-тела | По сети летит текст, не «живой» объект |
title, body, userId |
Поля, которые ждёт jsonplaceholder | У вашего API список полей будет в документации |
created.id |
Сервер «притворяется», что создал запись и вернул id | Учебный API не сохраняет навсегда — id всё равно приходит в ответе |
axios:
import axios from 'axios';
const { data: created } = await axios.post(
'https://jsonplaceholder.typicode.com/posts',
{ title: 'hello', body: 'text', userId: 1 },
);
console.log('Новый id:', created.id);
Разбор: axios сам ставит Content-Type: application/json и вызывает JSON.stringify за вас — вторым аргументом .post() передаётся обычный объект.
Что увидите:
Новый id: 101
(число может отличаться — jsonplaceholder возвращает фиктивный id.)
Частая ошибка: передать объект в body без JSON.stringify в fetch — сервер получит [object Object] и ответит 400 Bad Request.
Попробуйте: во вкладке Network откройте запрос posts → Payload — там ваш JSON.
Типовые запросы — углубление
1. Query-параметры
Задача: GET с фильтром — «все посты пользователя 1» (в URL после ?).
fetch:
const params = new URLSearchParams({ userId: '1' });
const url = `https://jsonplaceholder.typicode.com/posts?${params}`;
const res = await fetch(url);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const posts = await res.json();
console.log('Количество:', posts.length);
Разбор построчно:
| Строка | Что происходит | Зачем |
|---|---|---|
new URLSearchParams({ userId: '1' }) |
Строит строку параметров | Автоматически кодирует пробелы и спецсимволы |
`..?${params}` |
Склеивает базовый URL и userId=1 |
Итог: ../posts?userId=1 |
posts.length |
Длина массива | Ответ — список, не один объект |
axios:
import axios from 'axios';
const { data: posts } = await axios.get('https://jsonplaceholder.typicode.com/posts', {
params: { userId: 1 },
});
console.log('Количество:', posts.length);
Разбор: ключ params — axios сам добавит ?userId=1 к адресу. Число 1 можно писать без кавычек.
Что увидите: Количество: 10 (у userId=1 десять постов на jsonplaceholder).
Попробуйте: { params: { userId: 1, _limit: 3 } } — вернётся только 3 поста.
2. PUT, PATCH и DELETE
Задача: для отчёта показать все методы REST на одном URL /posts/1.
| Метод | Смысл простыми словами | Тело запроса |
|---|---|---|
| GET | Прочитать | Обычно пусто |
| POST | Создать новый | Новый объект |
| PUT | Заменить целиком | Полный объект со всеми полями |
| PATCH | Изменить часть | Только изменённые поля |
| DELETE | Удалить | Обычно пусто |
fetch — PUT:
const res = await fetch('https://jsonplaceholder.typicode.com/posts/1', {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
id: 1,
title: 'new title',
body: 'new body',
userId: 1,
}),
});
const updated = await res.json();
console.log(updated.title);
Разбор PUT: сервер ожидает все поля ресурса. Отправили только title — в строгих API остальное может обнулиться.
fetch — PATCH:
const res = await fetch('https://jsonplaceholder.typicode.com/posts/1', {
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ title: 'only title changed' }),
});
const patched = await res.json();
Разбор PATCH: «заплатка» — меняем одно поле, остальное сервер не трогает.
fetch — DELETE:
const res = await fetch('https://jsonplaceholder.typicode.com/posts/1', {
method: 'DELETE',
});
console.log('Статус:', res.status);
Разбор DELETE: тела обычно нет; успех — часто статус 200 или 204 (без тела).
axios — все три метода:
import axios from 'axios';
const BASE = 'https://jsonplaceholder.typicode.com/posts/1';
await axios.put(BASE, { id: 1, title: 'new', body: 'new', userId: 1 });
await axios.patch(BASE, { title: 'only title changed' });
await axios.delete(BASE);
Частая ошибка в лабораторных: перепутать PUT и PATCH. В отчёте напишите: PUT — полная замена, PATCH — частичное изменение.
3. Bearer-токен
Задача: передать секрет в заголовке — так работают JWT, API keys, «личный кабинет».
fetch:
const TOKEN = 'your-token-here';
const res = await fetch('https://httpbin.org/bearer', {
headers: {
Authorization: `Bearer ${TOKEN}`,
},
});
const data = await res.json();
console.log(data);
Разбор построчно:
| Строка | Что происходит | Зачем |
|---|---|---|
const TOKEN = '..' |
Переменная с секретом | В реальном проекте — из .env, не из Git |
headers: { Authorization: .. } |
HTTP-заголовок «кто вы» | Сервер читает его до тела запроса |
`Bearer ${TOKEN}` |
Формат: слово Bearer, пробел, токен | Стандарт OAuth2 / JWT |
httpbin /bearer |
Учебный сервер «эхо» | В ответе покажет, какой токен дошёл |
axios:
import axios from 'axios';
const TOKEN = 'your-token-here';
const { data } = await axios.get('https://httpbin.org/bearer', {
headers: { Authorization: `Bearer ${TOKEN}` },
});
console.log(data);
Попробуйте: TOKEN = 'test123' — в JSON ответа найдите "test123".
Никогда не коммитьте реальные ключи в репозиторий. В отчёте пишите: «токен берётся из переменной окружения process.env.API_TOKEN».
4. Форма и загрузка файла
Задача: отправить поля как HTML-форма (логин/пароль) или файл — multipart/form-data.
fetch — FormData:
const form = new FormData();
form.append('login', 'user');
form.append('password', 'pass');
// form.append('avatar', fileInput.files[0]); // раскомментируйте с <input type="file">
const res = await fetch('https://httpbin.org/post', {
method: 'POST',
body: form,
});
const echo = await res.json();
console.log(echo.form);
Разбор построчно:
| Строка | Что происходит | Зачем |
|---|---|---|
new FormData() |
Контейнер «поля формы» | Как виртуальная <form> |
form.append('login', 'user') |
Пара имя=значение | Имя login увидит сервер |
нет Content-Type |
Браузер сам поставит multipart/form-data с boundary |
Если поставить application/json вручную — сломается |
echo.form |
httpbin возвращает зеркало ваших полей | Проверка «дошло ли» |
axios:
import axios from 'axios';
const form = new FormData();
form.append('login', 'user');
form.append('password', 'pass');
const { data } = await axios.post('https://httpbin.org/post', form);
console.log(data.form);
Что увидите:
{ login: 'user', password: 'pass' }
(в консоли объект с вашими полями.)
5. Таймаут
Задача: сервер «думает» слишком долго — оборвать запрос через 5 секунд, чтобы интерфейс не завис.
fetch + AbortController:
Разбор построчно:
| Строка | Что происходит | Зачем |
|---|---|---|
async function fetchJson(..) |
Переиспользуемая функция | Один раз написали — вызываете из всего проекта |
{ timeoutMs = 5000 } = {} |
Параметр по умолчанию 5 сек | Можно передать { timeoutMs: 10000 } |
new AbortController() |
Объект «кнопка отмены» | Стандарт браузера для прерывания fetch |
setTimeout(() => controller.abort ..) |
Через N мс нажать «отмена» | Если ответ не успел — запрос обрывается |
signal: controller.signal |
Связь fetch с контроллером | Без signal abort не сработает |
finally { clearTimeout(timer) } |
Убрать таймер, если ответ пришёл раньше | Иначе таймеры копятся и «стреляют» позже |
axios:
import axios from 'axios';
const { data } = await axios.get('https://jsonplaceholder.typicode.com/posts/1', {
timeout: 5000,
});
console.log(data.title);
Разбор: одна строка timeout: 5000 — то же поведение, что ~15 строк с AbortController.
Попробуйте: fetchJson('https://httpbin.org/delay/5', { timeoutMs: 1000 }) — через 1 с в консоли AbortError.
6. Retry при сбое сервера
Задача: сервер на секунду «лежит» (502/503) — повторить запрос 2–3 раза с паузой.
Разбор логики:
| Шаг | Смысл |
|---|---|
for (let i = 0; i < attempts; i++) |
До 3 попыток |
status >= 500 |
Вина сервера — можно повторить |
(no retry) для 400/401/404 |
Ошибка клиента — повтор бессмысленен |
baseMs * 2 ** i |
Пауза растёт: 300 мс → 600 → 1200 |
await new Promise((r) => setTimeout(r, ..)) |
«Подождать» без блокировки вкладки |
Попробуйте: URL https://httpbin.org/status/503 и attempts: 2 — в Network две попытки.
7. Interceptors в axios
Задача: один раз прописать токен и обработку 401 — для всех запросов приложения.
Разбор .. (spread): если token есть — в заголовки добавится Authorization; если нет — поле не попадёт в объект.
8. Параллельные запросы
Задача: загрузить пост и комментарии одновременно — быстрее, чем два раза подряд.
fetch:
Разбор:
| Строка | Смысл |
|---|---|
Promise.all([..]) |
Запускает оба fetch параллельно |
Первый Promise.all |
Ждёт HTTP-ответы (заголовки) |
Второй Promise.all |
Параллельно читает тела JSON |
comments.length |
Комментарии — массив |
axios:
import axios from 'axios';
const [postRes, commentsRes] = await Promise.all([
axios.get('https://jsonplaceholder.typicode.com/posts/1'),
axios.get('https://jsonplaceholder.typicode.com/posts/1/comments'),
]);
console.log(postRes.data.title, 'комментариев:', commentsRes.data.length);
Что увидите: заголовок поста и число комментариев (обычно 5).
9. React — загрузка в useEffect
Задача: открыли страницу /post/1 → показали «Загрузка…» → заголовок или текст ошибки.
Разбор построчно:
| Строка | Что происходит | Зачем |
|---|---|---|
useState(null) |
Три «ячейки памяти» компонента | post, loading, error — стандартный набор для API |
useEffect(.., [id]) |
Запуск при монтировании и при смене id | Перешли с /post/1 на /post/2 — новый запрос |
async function load() внутри effect |
fetch нельзя передать «голым» async в useEffect | Обёртка — обычный паттерн React |
setLoading(true) |
Показать спиннер | Пользователь видит, что идёт загрузка |
{ signal: controller.signal } |
Привязка к AbortController | Старый запрос отменится при смене id |
return () => controller.abort() |
Cleanup при размонтировании | Ушли со страницы — не обновлять state «в пустоту» |
e.name !== 'AbortError' |
Отмена — не ошибка для пользователя | Иначе мелькнёт «Ошибка: AbortError» |
if (loading) return .. |
Условный рендер | Три экрана: загрузка / ошибка / данные |
Сценарий «гонка»: пользователь быстро кликнул post/1 → post/2. Без abort() ответ от «1» может прийти после «2» и перезаписать экран. AbortController это предотвращает.
10. CORS — «Failed to fetch»
Задача: в Postman и curl всё работает, в React — красное Failed to fetch. Почему?
Правило браузера: JavaScript не может прочитать ответ с другого домена, если сервер не разрешил заголовком Access-Control-Allow-Origin.
| Инструмент | Проверяет CORS? |
|---|---|
| curl | Нет |
| Postman | Нет |
| Node.js fetch | Нет |
| Браузер | Да |
Алгоритм отладки:
- Тот же URL в curl — примеры. Если там 200 — бэкенд жив.
- F12 → Network — запрос мог уйти, статус 200, но консоль красная.
- Решение: настроить CORS на сервере или dev-proxy в Vite:
// vite.config.js — пример
export default {
server: {
proxy: {
'/api': 'http://127.0.0.1:8080',
},
},
};
Разбор proxy: браузер стучится на тот же origin (localhost:5173/api/..), Vite пересылает на бэкенд — CORS не мешает.
11. localhost — свой API на компьютере
Задача: бэкенд крутится у вас на http://127.0.0.1:8080 — проверить из JS.
const res = await fetch('http://127.0.0.1:8080/api/health');
console.log('Статус:', res.status);
console.log('Тело:', await res.text());
Разбор:
| Строка | Смысл |
|---|---|
127.0.0.1 |
«Этот компьютер» — loopback |
:8080 |
Порт — должен совпадать с тем, что слушает сервер |
await res.text() |
Если ответ не JSON, а plain text «OK» |
Перед запуском: сервер уже должен работать (npm run dev, uvicorn, dotnet run…). Иначе Failed to fetch — «ничего не слушает порт».
Переиспользуемые базы
Структура папок API-слоя
src/
api/
http.js # fetchJson или axios.create
posts.js # getPost, createPost
users.js # getUser
// api/posts.js
import { apiRequest } from './http.js';
export function getPost(id) {
return apiRequest(`/posts/${id}`);
}
export function createPost(body) {
return apiRequest('/posts', { method: 'POST', body });
}
Зачем так делать:
- компоненты React не знают полный URL — только
getPost(1); - токен и обработка ошибок — в одном файле
http.js; - в лабораторной легко показать: «слой API отделён от UI».
Частые вопросы (коротко)
Почему fetch не падает на 404?
Сеть ответила — Promise выполнился. HTTP 404 — это «ответ с ошибкой», не обрыв связи. Проверяйте res.ok.
Зачем два await подряд?
Первый — ждём заголовки HTTP. Второй — читаем тело (JSON). Оба шага асинхронные.
Как отправить POST с JSON?
fetch: method: 'POST', заголовок Content-Type: application/json, body: JSON.stringify(obj). axios: axios.post(url, obj).
fetch или axios для курсовой?
Оба зачтут. fetch — меньше зависимостей; axios — меньше строк и встроенный timeout.
Где хранить API key?
Секреты — на сервере. В клиентском JS ключ виден любому в DevTools.
Что такое res.json() vs res.text()?
.json() — парсит {..} в объект. .text() — сырая строка (HTML, plain text).
Типичные ошибки
| Симптом | Частая причина | Что сделать |
|---|---|---|
Failed to fetch |
CORS, сервер выключен, mixed HTTP/HTTPS | curl; проверить порт; proxy в Vite |
Unexpected token < in JSON |
Сервер вернул HTML-страницу ошибки | res.text() и посмотреть; проверить URL |
401 Unauthorized |
Нет заголовка Authorization | Bearer ${token} |
data is undefined |
Забыли await перед res.json() |
Два await: fetch и json |
Cannot use import outside a module |
Node без ESM | Файл .mjs или "type":"module" |
| Старые данные на экране | Медленный ответ пришёл последним | AbortController в useEffect |
| Двойная отправка формы | Два клика по кнопке | disabled={loading} на кнопке |
Шпаргалка — скопировать в тетрадь
Чек-лист перед сдачей лабораторной
- В отчёте есть код и фрагмент ответа (JSON или код статуса).
- Для POST указан JSON и правильный метод.
- Ошибки HTTP обработаны (
res.okилиtry/catch). - Токены не в Git.
- При
Failed to fetch— скрин curl с тем же URL. - Указан таймаут или пояснение, зачем он нужен.
Связанные материалы
| Тема | Ссылка |
|---|---|
| curl, health-check, Python requests | curl / fetch — API-запросы |
| Массивы, debounce, общий JS | Примеры JavaScript |
| DOM в браузере | JavaScript DOM — 30 приёмов |
| Promise, async/await | Асинхронное программирование |
| Каркас API-клиента | Практика JavaScript |
| AbortController, SSE | Отмена запросов |
| React и данные | React — о разделе |
| Формат галереи | Файлы и текст Python |