Содержание статьи

Современные веб-приложения активно взаимодействуют с сервером без перезагрузки страницы. Для этого JavaScript использует инструменты fetch и XMLHttpRequest, позволяющие получать или отправлять данные, работать с API и обрабатывать ответы асинхронно.
Метод fetch() предоставляет удобный интерфейс для выполнения HTTP-запросов. Он поддерживает все стандартные методы – GET, POST, PUT, DELETE – и возвращает промис, что упрощает работу с асинхронными операциями. В отличие от старого подхода с XMLHttpRequest, код с fetch выглядит чище и легче читается.
Чтобы отправить запрос, требуется указать URL-адрес и, при необходимости, параметры: метод, тело запроса, заголовки и настройки авторизации. Например, при отправке данных формы их можно преобразовать в JSON с помощью JSON.stringify() и передать на сервер через POST-запрос.
Понимание принципов работы HTTP-запросов в JavaScript позволяет создавать динамичные интерфейсы, обрабатывать ошибки соединения, проверять статусы ответов и корректно передавать пользовательские данные. Это ключевой навык для разработки интерактивных веб-сервисов и работы с внешними API.
Разница между XMLHttpRequest и fetch: что выбрать

XMLHttpRequest – старый интерфейс, появившийся ещё до стандарта ES6. Он позволяет отправлять HTTP-запросы и отслеживать их состояние с помощью событий onreadystatechange. Однако его синтаксис громоздкий: нужно вручную открывать соединение, устанавливать заголовки и обрабатывать коды состояния.
fetch – современная альтернатива, основанная на промисах. Она поддерживает асинхронное выполнение, что делает код короче и читаемее. Пример простого запроса выглядит так: fetch(‘/api/data’).then(response => response.json()). Для асинхронных операций удобно использовать async/await.
Основное отличие заключается в обработке данных и ошибок. fetch не вызывает исключение при ответе с кодом ошибки, если соединение установлено, – проверку статуса нужно выполнять вручную через response.ok. В то время как XMLHttpRequest сообщает о подобных состояниях через события и свойства объекта.
Для современных проектов рекомендуется использовать fetch, так как он поддерживается всеми актуальными браузерами и лучше интегрируется с модульной архитектурой JavaScript. XMLHttpRequest имеет смысл применять только при необходимости поддержки устаревших окружений или для специфичных сценариев, где требуется более детальный контроль над состоянием соединения.
Как отправить GET-запрос с помощью fetch
Метод fetch() используется для выполнения запросов к серверу по указанному адресу. Для GET-запроса достаточно передать только URL, если не требуется дополнительных параметров. Пример простого запроса:
fetch(‘https://api.example.com/users’)
.then(response => response.json())
.then(data => console.log(data));
Функция возвращает промис, который сначала содержит объект Response. Чтобы получить данные в формате JSON, нужно вызвать метод response.json(). Если сервер возвращает текст, можно использовать response.text().
Проверка статуса ответа выполняется через свойство response.ok. Например, чтобы обработать ошибку 404 или 500, можно добавить условие:
if (!response.ok) { throw new Error(‘Ошибка запроса: ‘ + response.status); }
Запросы с параметрами можно формировать через строку запроса. Для этого удобно использовать URLSearchParams:
const params = new URLSearchParams({ user: ‘admin’, limit: 10 });
fetch(‘https://api.example.com/data?’ + params);
При работе с API рекомендуется выносить базовый URL в переменную и использовать try…catch для обработки ошибок в асинхронных функциях. Это улучшает читаемость кода и упрощает повторное использование запросов в разных частях приложения.
Отправка POST-запроса с передачей данных в формате JSON
POST-запрос применяется для передачи данных на сервер. В JavaScript его удобно выполнять с помощью функции fetch(), указывая метод, заголовки и тело запроса. Перед отправкой объект с данными нужно преобразовать в строку с помощью JSON.stringify().
Пример базового POST-запроса:
fetch(‘https://api.example.com/users’, {
method: ‘POST’,
headers: { ‘Content-Type’: ‘application/json’ },
body: JSON.stringify({ name: ‘Ivan’, age: 28 })
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error(‘Ошибка:’, error));
Заголовок Content-Type сообщает серверу, что тело запроса содержит данные в формате JSON. Если сервер требует авторизацию, можно добавить токен в заголовки:
‘Authorization’: ‘Bearer ‘ + token
Чтобы структурировать параметры POST-запроса, удобно использовать таблицу:
| Параметр | Описание |
|---|---|
| method | Указывает тип запроса – POST |
| headers | Определяет тип передаваемых данных и возможные параметры авторизации |
| body | Содержит сериализованные данные JSON, отправляемые на сервер |
При работе с асинхронными функциями можно использовать async/await для сокращения цепочки промисов и удобной обработки ошибок через try…catch. Это упрощает контроль над результатом выполнения запроса и реакцией на сбои соединения.
Обработка ответов сервера и работа с промисами
Метод fetch() возвращает промис, который разрешается объектом Response. Этот объект содержит информацию о статусе, заголовках и теле ответа. Чтобы извлечь данные, необходимо вызвать один из методов: response.json(), response.text() или response.blob() – в зависимости от формата данных, возвращаемых сервером.
Пример базовой обработки ответа:
fetch(‘/api/data’)
.then(response => {
if (!response.ok) throw new Error(‘Ошибка: ‘ + response.status);
return response.json();
})
.then(data => console.log(data))
.catch(error => console.error(‘Сбой запроса:’, error));
Промисы позволяют выстраивать последовательность операций, выполняющихся после завершения запроса. Это исключает необходимость вложенных колбэков и делает код линейным. Если нужно выполнить несколько запросов одновременно, можно использовать Promise.all(), который ожидает завершения всех промисов и возвращает массив результатов.
Для улучшения читаемости и управления ошибками применяется синтаксис async/await:
async function getData() {
try {
const response = await fetch(‘/api/info’);
if (!response.ok) throw new Error(response.status);
const data = await response.json();
console.log(data);
} catch (error) {
console.error(‘Ошибка запроса:’, error);
}
}
Такая структура делает обработку ответов более наглядной, а ошибки соединения и некорректные статусы можно перехватывать в одном блоке. Это особенно удобно при работе с API, где важна предсказуемая реакция на результат запроса.
Передача заголовков и токенов авторизации в запросе

Заголовки HTTP позволяют передавать дополнительную информацию серверу: тип содержимого, данные авторизации, ключи API и параметры кеширования. В JavaScript они указываются в объекте headers внутри параметров функции fetch().
Пример добавления заголовков в запрос:
fetch(‘https://api.example.com/data’, {
method: ‘GET’,
headers: {
‘Content-Type’: ‘application/json’,
‘Accept’: ‘application/json’
}
});
Если сервер требует проверку пользователя, используется токен авторизации. Его можно передать в заголовке Authorization:
const token = ‘your_access_token’;
fetch(‘https://api.example.com/secure’, {
method: ‘GET’,
headers: {
‘Authorization’: ‘Bearer ‘ + token,
‘Content-Type’: ‘application/json’
}
});
Основные типы заголовков, применяемых при отправке запросов:
- Content-Type – указывает формат передаваемых данных (например, application/json).
- Accept – сообщает серверу, в каком формате клиент ожидает ответ.
- Authorization – используется для передачи токенов доступа, обычно в виде схемы Bearer.
- Cache-Control – управляет кэшированием на стороне клиента и прокси.
- X-Requested-With – помогает серверу различать AJAX-запросы.
При работе с API токен стоит хранить в sessionStorage или localStorage и передавать его только через защищённое соединение HTTPS. Это предотвращает утечку данных при перехвате трафика.
Если необходимо передавать разные заголовки в зависимости от условий, их можно формировать динамически:
const headers = new Headers();
headers.append(‘Content-Type’, ‘application/json’);
if (token) headers.append(‘Authorization’, ‘Bearer ‘ + token);
fetch(‘/api/check’, { headers });
Гибкое управление заголовками позволяет контролировать поведение запросов и гарантировать корректную авторизацию при обращении к защищённым ресурсам.
Обработка ошибок при выполнении сетевых запросов
Сетевые запросы могут завершаться сбоем по разным причинам: недоступность сервера, тайм-ауты, ошибки авторизации или неверные данные. В JavaScript обработка ошибок выполняется с помощью промисов и конструкции try…catch при использовании async/await.
Рекомендации для корректной обработки ошибок:
- Проверять статус ответа через response.ok и response.status. Например, if (!response.ok) throw new Error(response.status);
- Использовать catch для перехвата сетевых ошибок, которые не связаны с HTTP-статусом.
- Разделять обработку ошибок на клиентские (например, JSON не удалось распарсить) и серверные (код 4xx или 5xx).
- При работе с несколькими запросами применять Promise.allSettled(), чтобы получить результаты всех промисов, даже если некоторые завершились ошибкой.
Пример обработки ошибок с использованием async/await:
async function fetchData() {
try {
const response = await fetch(‘/api/items’);
if (!response.ok) throw new Error(‘Ошибка сервера: ‘ + response.status);
const data = await response.json();
console.log(data);
} catch (error) {
console.error(‘Сетевой сбой или ошибка обработки данных:’, error);
}
}
Для удобства пользователей стоит информировать их о сбоях через уведомления или визуальные индикаторы и предусматривать повтор запроса при временных проблемах с сетью. Это повышает надежность взаимодействия с сервером и снижает вероятность потери данных.
Использование async/await для асинхронных запросов
Синтаксис async/await упрощает работу с промисами, делая код линейным и читаемым. Функция помечается ключевым словом async, а выполнение асинхронного запроса приостанавливается с помощью await до получения результата.
Пример запроса с использованием async/await:
async function getUsers() {
try {
const response = await fetch(‘https://api.example.com/users’);
if (!response.ok) throw new Error(‘Ошибка: ‘ + response.status);
const data = await response.json();
console.log(data);
} catch (error) {
console.error(‘Сбой запроса:’, error);
}
}
Использование await позволяет обращаться к данным сразу после завершения запроса без цепочек then, что упрощает обработку ошибок и логирование. Для нескольких последовательных запросов можно использовать несколько await подряд, сохраняя порядок выполнения:
const userResponse = await fetch(‘/api/user’);
const userData = await userResponse.json();
const postsResponse = await fetch(`/api/posts?userId=${userData.id}`);
const postsData = await postsResponse.json();
Для параллельного выполнения нескольких независимых запросов рекомендуется сочетать async/await с Promise.all(), чтобы сократить время ожидания и получить массив результатов одновременно. Это повышает производительность при работе с большим количеством асинхронных операций.
Отправка формы без перезагрузки страницы с помощью JavaScript
Для отправки формы без обновления страницы используют событие submit и метод preventDefault(), чтобы предотвратить стандартное поведение браузера. Данные формы можно собрать с помощью FormData или преобразовать в JSON для отправки через fetch().
Пример отправки формы с JSON:
const form = document.querySelector(‘#userForm’);
form.addEventListener(‘submit’, async (event) => {
event.preventDefault();
const formData = new FormData(form);
const data = Object.fromEntries(formData.entries());
try {
const response = await fetch(‘/api/submit’, {
method: ‘POST’,
headers: { ‘Content-Type’: ‘application/json’ },
body: JSON.stringify(data)
});
if (!response.ok) throw new Error(response.status);
const result = await response.json();
console.log(result);
} catch (error) {
console.error(‘Ошибка отправки формы:’, error);
}
});
При использовании FormData без преобразования в JSON удобно отправлять файлы и изображения. Для этого достаточно указать body: formData и исключить заголовок Content-Type, так как браузер автоматически установит корректный multipart-формат.
Рекомендации:
- Валидация данных перед отправкой, чтобы сервер получал корректные значения.
- Обработка ошибок сервера и отображение сообщений пользователю.
- При необходимости блокировать кнопку отправки до завершения запроса, чтобы предотвратить повторную отправку.
Такой подход позволяет создавать динамичные формы и улучшает взаимодействие с пользователем без перезагрузки страницы.
Вопрос-ответ:
В чем разница между XMLHttpRequest и fetch?
XMLHttpRequest — старый интерфейс для отправки HTTP-запросов, который использует события для отслеживания состояния соединения. Его синтаксис более громоздкий и требует явного открытия соединения и обработки кодов ответа. Fetch основан на промисах и позволяет писать код асинхронно, проще работать с JSON и управлять последовательностью запросов с помощью then или async/await. Для современных проектов чаще используют fetch, а XMLHttpRequest применяется для поддержки старых браузеров или специфичных задач.
Как отправить GET-запрос и обработать ответ в формате JSON?
Для GET-запроса достаточно вызвать fetch с URL: fetch(‘/api/data’). После этого промис возвращает объект Response. Чтобы получить данные в формате JSON, нужно вызвать response.json(). Для проверки успешности запроса используется response.ok. Пример обработки: fetch(‘/api/data’).then(response => { if (!response.ok) throw new Error(response.status); return response.json(); }).then(data => console.log(data)). Такой подход позволяет безопасно работать с ответами и обрабатывать ошибки сервера.
Как передавать данные формы на сервер без перезагрузки страницы?
Для этого используют событие submit и метод event.preventDefault(). Данные формы собираются через FormData или преобразуются в JSON с помощью Object.fromEntries(formData.entries()). Затем выполняется POST-запрос через fetch: fetch(‘/api/submit’, { method: ‘POST’, headers: { ‘Content-Type’: ‘application/json’ }, body: JSON.stringify(data) }). Ошибки можно обработать через try…catch, а результат отобразить пользователю без перезагрузки страницы.
Как правильно обрабатывать ошибки при сетевых запросах?
Ошибки делятся на сетевые и серверные. Сетевые ошибки (например, недоступность сервера) перехватываются через catch или блок try…catch при async/await. Серверные ошибки проверяются по свойству response.ok или коду response.status. Для нескольких параллельных запросов удобно использовать Promise.allSettled(), чтобы получить результат всех промисов и обработать ошибки отдельно. Также рекомендуется информировать пользователя о сбоях и предусматривать повтор запроса при временных проблемах.
