Чтобы получить данные с сервера или отправить форму без перезагрузки страницы, в JavaScript есть встроенная функция fetch. Она работает во всех современных браузерах и в Node.js без дополнительных библиотек. Ниже - как ей пользоваться, чем может быть удобнее библиотека Axios и что делать со старым кодом на XMLHttpRequest и jQuery.
fetch: GET-запрос
const response = await fetch('https://api.example.com/users');
const users = await response.json();
console.log(users);
fetch возвращает промис с объектом ответа. Тело ответа читается отдельно, тоже асинхронно:
response.json()- разобрать JSON;response.text()- получить текст;response.blob()- получить файл (например, картинку);response.formData(),response.arrayBuffer()- для особых случаев.
await работает внутри функций, объявленных как async, и на верхнем уровне модулей. Без async/await тот же код пишется через then:
fetch('https://api.example.com/users')
.then(response => response.json())
.then(users => console.log(users));
Параметры запроса удобно собирать через URLSearchParams - он сам экранирует значения:
const params = new URLSearchParams({ q: 'ноутбук', page: 2 });
const response = await fetch(`https://api.example.com/search?${params}`);
Обработка ошибок

Важная особенность fetch: промис отклоняется только при сетевой ошибке (нет соединения, сервер недоступен, запрос заблокирован политикой CORS). Ответы с кодами 404 или 500 считаются успешными - проверять код нужно самому:
async function getJson(url) {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
return response.json();
}
try {
const data = await getJson('https://api.example.com/users/42');
console.log(data);
} catch (error) {
console.error('Не удалось загрузить данные:', error.message);
}
response.ok равен true для кодов 200-299. Сам код - в response.status.
POST-запрос с JSON
const response = await fetch('https://api.example.com/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ name: 'Иван', email: 'ivan@example.com' }),
});
const created = await response.json();
Объект нужно превратить в строку через JSON.stringify и указать заголовок Content-Type, иначе сервер не поймёт формат.
Методы PUT, PATCH и DELETE отправляются так же, меняется только method.
Отправка формы и файлов
FormData собирает поля формы, включая файлы:
const form = document.querySelector('#upload-form');
form.addEventListener('submit', async (event) => {
event.preventDefault();
const response = await fetch('/upload', {
method: 'POST',
body: new FormData(form),
});
if (response.ok) {
alert('Файл загружен');
}
});
Заголовок Content-Type для FormData указывать не нужно: браузер сам поставит multipart/form-data с правильной границей частей.
Заголовки, куки и авторизация
const response = await fetch('https://api.example.com/profile', {
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json',
},
credentials: 'include',
});
credentials: 'include' отправляет куки и на другой домен (по умолчанию куки отправляются только на свой). Заголовки ответа читаются через response.headers.get('Content-Type').
Тайм-аут и отмена запроса

У fetch нет встроенного тайм-аута, но есть сигнал отмены:
const response = await fetch(url, { signal: AbortSignal.timeout(5000) });
Через 5 секунд запрос будет прерван с ошибкой TimeoutError. Отменить запрос вручную, например, когда пользователь ушёл со страницы или ввёл новый поисковый запрос:
const controller = new AbortController();
fetch(url, { signal: controller.signal })
.then(response => response.json())
.catch(error => {
if (error.name === 'AbortError') {
console.log('Запрос отменён');
}
});
controller.abort();
Несколько запросов параллельно
const [users, orders] = await Promise.all([
getJson('/api/users'),
getJson('/api/orders'),
]);
Promise.all завершится ошибкой, если упадёт хотя бы один запрос. Если нужны результаты всех, даже при частичных ошибках, используйте Promise.allSettled.
CORS
Если страница на одном домене обращается к API на другом, браузер применяет политику CORS: запрос пройдёт, только если сервер разрешил это заголовком Access-Control-Allow-Origin. Ошибка «blocked by CORS policy» в консоли означает, что настраивать нужно сервер, а не клиентский код. Параметр mode: 'no-cors' проблему не решает: запрос уйдёт, но прочитать ответ будет нельзя.
Axios
Axios - популярная библиотека для HTTP-запросов. Она работает в браузере и Node.js и делает некоторые вещи удобнее:
- JSON разбирается и отправляется автоматически;
- ответы с кодами ошибок (4xx, 5xx) сразу отклоняют промис;
- есть встроенный тайм-аут и перехватчики (interceptors) для общих заголовков и обработки ошибок;
- можно создать экземпляр с базовым адресом и общими настройками.
npm install axios
import axios from 'axios';
const api = axios.create({
baseURL: 'https://api.example.com',
timeout: 5000,
});
api.interceptors.request.use(config => {
config.headers.Authorization = `Bearer ${localStorage.getItem('token')}`;
return config;
});
try {
const { data } = await api.get('/users', { params: { page: 2 } });
await api.post('/users', { name: 'Иван' });
} catch (error) {
console.error(error.response?.status, error.message);
}
Для небольших проектов достаточно fetch и маленькой обёртки вроде getJson выше. Axios оправдан в приложениях с десятками запросов к одному API, где перехватчики и общие настройки экономят код.
XMLHttpRequest и jQuery
XMLHttpRequest - старый интерфейс, на котором построены прежние AJAX-библиотеки. В новом коде он не нужен, но встречается в старых проектах:
const xhr = new XMLHttpRequest();
xhr.open('GET', '/api/users');
xhr.responseType = 'json';
xhr.onload = () => {
if (xhr.status >= 200 && xhr.status < 300) {
console.log(xhr.response);
}
};
xhr.onerror = () => console.error('Сетевая ошибка');
xhr.send();
У него есть одно преимущество перед fetch: событие upload.onprogress, которое показывает прогресс загрузки файла на сервер. Если нужен индикатор загрузки, это до сих пор самый простой способ.
В jQuery запросы делаются через $.ajax, $.get и $.post. Если jQuery на сайте нужен только для запросов, его можно заменить на fetch:
// было
$.post('/api/users', { name: 'Иван' }, data => console.log(data));
// стало
fetch('/api/users', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({ name: 'Иван' }),
}).then(r => r.json()).then(data => console.log(data));
$.post по умолчанию отправляет данные как поля формы, а не как JSON, поэтому в замене используется URLSearchParams - так серверный код не придётся менять.
Node.js
В современных версиях Node.js fetch встроен и работает так же, как в браузере, включая AbortSignal.timeout. Ограничений CORS в Node.js нет: это защита браузера, а не сервера.





Комментарии
Комментариев пока нет - будьте первым.