Сетевые запросы в JS - эффективные методы и инструменты
HTTP запросы в JavaScript: обзор и эффективные решения
Как выполнить HTTP запросы в JavaScript с помощью fetch?
fetch - это встроенный API для выполнения сетевых запросов. Он возвращает Promise, что упрощает асинхронную обработку.
fetch('https://api.example.com/data')
.then(response => {
if (!response.ok) throw new Error('Ошибка ' + response.status);
return response.json();
})
.then(data => console.log(data))
.catch(error => console.error('Ошибка:', error));Js запросы (http запросы в javascript)
После fetch нужно преобразовать ответ в нужный формат (json, text, blob). Важно проверять response.ok, так как fetch не отклоняет Promise при HTTP ошибках (4xx, 5xx).
Типичные ошибки: пропущена проверка статуса, не вызван метод .json(), CORS политика, неверный URL.
Как выполнить HTTP запросы с помощью XMLHttpRequest?
XMLHttpRequest - классический способ, поддерживает события и прогресс загрузки.
const xhr = new XMLHttpRequest();
xhr.open('GET', 'https://api.example.com/data');
xhr.onload = function() {
if (xhr.status >= 200 && xhr.status < 300) {
console.log(JSON.parse(xhr.responseText));
} else {
console.error('Ошибка ' + xhr.status);
}
};
xhr.onerror = function() {
console.error('Сетевая ошибка');
};
xhr.send();
Методы open, onload, send. Можно слушать onprogress для отслеживания загрузки.
Проблемы: больше кода, сложность с синхронными запросами (устарело), необходимость вручную обрабатывать разные типы данных.
Как упростить асинхронные запросы с async/await?
Синтаксис async/await делает код более читаемым, похожим на синхронный.
async function fetchData() {
try {
const response = await fetch('https://api.example.com/data');
if (!response.ok) throw new Error('Ошибка ' + response.status);
const data = await response.json();
console.log(data);
} catch (error) {
console.error('Ошибка:', error);
}
}
fetchData();
Функция объявляется с ключевым словом async, перед промисами ставится await, ошибки обрабатываются через try/catch.
Ошибки: await вне функции async, забыли обернуть вызов в try/catch.
Как отправить данные на сервер в формате JSON?
Для POST запроса с JSON нужно указать method, заголовки и тело.
fetch('https://api.example.com/data', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: 'Иван', age: 30 })
})
.then(response => response.json())
.then(data => console.log(data));
Тело запроса преобразуется в строку через JSON.stringify, заголовок Content-Type обязателен.
Ошибки: неверный Content-Type, некорректный JSON в теле, отсутствие метода.
Как передать файлы и данные формы через HTTP?
Для отправки форм с файлами используется FormData.
const form = new FormData();
form.append('username', 'user1');
form.append('avatar', fileInput.files[0]);
fetch('/upload', {
method: 'POST',
body: form
})
.then(response => response.json())
.then(data => console.log(data));
FormData автоматически устанавливает multipart/form-data, заголовок Content-Type указывать не нужно.
Проблемы: сервер должен поддерживать multipart, размер файла может быть ограничен, не забыть проверить fileInput.
Как добавить пользовательские заголовки к запросу?
Заголовки передаются в объекте headers.
fetch('https://api.example.com/data', {
headers: {
'Authorization': 'Bearer token123',
'X-Custom-Header': 'customValue'
}
})
.then(response => response.json())
.then(data => console.log(data));
Можно добавить несколько заголовков, включая авторизацию.
Ошибки: CORS может запретить некоторые заголовки, неверное имя заголовка.
Как корректно обрабатывать ошибки при HTTP запросах?
Необходимо проверять статус ответа и обрабатывать как сетевые, так и HTTP ошибки.
fetch('/data')
.then(response => {
if (!response.ok) {
throw new Error('HTTP ошибка ' + response.status);
}
return response.json();
})
.catch(error => {
if (error.name === 'TypeError') {
console.error('Сетевая ошибка');
} else {
console.error('Ошибка ответа:', error.message);
}
});
Сетевые ошибки (например, отсутствие интернета) вызывают TypeError, HTTP ошибки обрабатываются через свой статус.
Распространённые ошибки: отсутствие catch, игнорирование response.ok, путаница между типами ошибок.
Какие преимущества дает библиотека axios?
axios - популярная библиотека, упрощающая HTTP запросы, автоматически преобразует JSON, поддерживает interceptor'ы, таймауты, отмену запросов.
// Установка: npm install axios
import axios from 'axios';
axios.get('https://api.example.com/data')
.then(response => console.log(response.data))
.catch(error => console.error('Ошибка:', error));
В отличие от fetch, axios автоматически парсит JSON, отклоняет Promise при HTTP ошибках (4xx, 5xx), имеет удобный API для заголовков и параметров.
Недостатки: дополнительная зависимость, размер библиотеки, может быть избыточной для простых запросов.
Расширенные примеры HTTP запросов
Пример 1: Параллельные запросы с Promise.all
const urls = ['https://api.example.com/users', 'https://api.example.com/posts', 'https://api.example.com/comments'];
const fetchAll = async () => {
try {
const promises = urls.map(url => fetch(url).then(res => res.json()));
const results = await Promise.all(promises);
console.log('Получены данные:', results);
} catch (error) {
console.error('Ошибка при загрузке:', error);
}
};
fetchAll();
// Результат: массив из трёх объектов (users, posts, comments)
Пример 2: Отмена запроса с AbortController
const controller = new AbortController();
const signal = controller.signal;
setTimeout(() => controller.abort(), 3000); // отмена через 3 секунды
fetch('https://api.example.com/large-data', { signal })
.then(response => response.json())
.then(data => console.log(data))
.catch(error => {
if (error.name === 'AbortError') {
console.log('Запрос был отменён');
} else {
console.error('Ошибка:', error);
}
});
// Вывод: 'Запрос был отменён'
Пример 3: Прогресс загрузки через XMLHttpRequest
const xhr = new XMLHttpRequest();
xhr.open('GET', 'https://api.example.com/bigfile');
xhr.onprogress = function(event) {
if (event.lengthComputable) {
const percent = (event.loaded / event.total) * 100;
console.log(`Загружено ${percent.toFixed(1)}%`);
}
};
xhr.onload = function() {
console.log('Загрузка завершена');
};
xhr.send();
// Вывод: 'Загружено 23.5%', 'Загружено 57.2%', ..., 'Загрузка завершена'
Пример 4: Интерцепторы в axios
import axios from 'axios';
axios.interceptors.request.use(config => {
config.headers['Authorization'] = 'Bearer ' + localStorage.getItem('token');
console.log('Запрос отправлен', config);
return config;
}, error => Promise.reject(error));
axios.interceptors.response.use(response => {
console.log('Ответ получен', response);
return response;
}, error => {
if (error.response.status === 401) {
console.log('Перенаправление на страницу логина');
}
return Promise.reject(error);
});
axios.get('/api/profile');
// В консоли: 'Запрос отправлен' затем 'Ответ получен'
Пример 5: Таймаут запроса с axios
axios.get('https://api.example.com/slow', { timeout: 5000 })
.then(response => console.log(response.data))
.catch(error => {
if (error.code === 'ECONNABORTED') {
console.log('Таймаут запроса');
} else {
console.error('Ошибка:', error);
}
});
// Вывод: 'Таймаут запроса'
Пример 6: DELETE запрос с fetch
fetch('https://api.example.com/users/123', { method: 'DELETE' })
.then(response => {
if (response.status === 204) {
console.log('Ресурс удалён');
} else {
return response.json();
}
})
.then(data => console.log(data));
// Вывод: 'Ресурс удалён' или объект с подтверждением
Пример 7: Загрузка изображения как Blob
fetch('https://example.com/image.png')
.then(response => response.blob())
.then(blob => {
const imgUrl = URL.createObjectURL(blob);
document.getElementById('myImage').src = imgUrl;
})
.catch(error => console.error('Ошибка загрузки изображения:', error));
// Результат: изображение отображается на странице