- Home »

Использование Axios в чистом JavaScript: руководство для начинающих
Axios — это мощная HTTP-библиотека для JavaScript, которая превратилась в фактический стандарт для работы с API. Если вы настраиваете сервер, создаете административные панели или разрабатываете мониторинг инфраструктуры, то без качественного HTTP-клиента никуда. Axios предоставляет все необходимые инструменты: интерсепторы, автоматическое преобразование JSON, timeout’ы, отмену запросов и многое другое. В этой статье мы разберем, как максимально эффективно использовать Axios в чистом JavaScript без фреймворков — от базовых запросов до продвинутых техник автоматизации.
Как работает Axios под капотом
Axios построен поверх XMLHttpRequest в браузере и http-модуля в Node.js. Основное преимущество перед встроенным fetch() — это богатые возможности конфигурации и обработки ошибок из коробки. Библиотека использует систему промисов, но с дополнительными возможностями отмены запросов через AbortController.
Внутри Axios реализован паттерн interceptor, который позволяет перехватывать и модифицировать запросы/ответы на лету. Это особенно полезно для добавления токенов авторизации, логирования или обработки ошибок на глобальном уровне.
Быстрая установка и базовая настройка
Для начала работы с Axios есть несколько способов подключения:
// Через CDN (для тестирования)
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
// Через npm (рекомендуется для production)
npm install axios
// Через yarn
yarn add axios
Базовая конфигурация для серверных задач:
// Создание экземпляра с базовыми настройками
const api = axios.create({
baseURL: 'https://api.example.com',
timeout: 5000,
headers: {
'Content-Type': 'application/json',
'User-Agent': 'ServerBot/1.0'
}
});
// Глобальные настройки для всех запросов
axios.defaults.timeout = 10000;
axios.defaults.headers.common['Authorization'] = 'Bearer ' + token;
Практические примеры использования
Базовые HTTP-операции
// GET-запрос для получения статистики сервера
async function getServerStats() {
try {
const response = await axios.get('/api/server/stats');
console.log('CPU Usage:', response.data.cpu);
console.log('Memory Usage:', response.data.memory);
return response.data;
} catch (error) {
console.error('Error fetching server stats:', error.message);
throw error;
}
}
// POST-запрос для создания нового пользователя
async function createUser(userData) {
try {
const response = await axios.post('/api/users', userData, {
headers: {
'Content-Type': 'application/json'
}
});
return response.data;
} catch (error) {
if (error.response.status === 409) {
console.error('User already exists');
}
throw error;
}
}
// PUT-запрос для обновления конфигурации
async function updateConfig(configData) {
const response = await axios.put('/api/config', configData);
return response.data;
}
// DELETE-запрос для удаления логов
async function cleanupLogs(olderThan) {
const response = await axios.delete(`/api/logs?older_than=${olderThan}`);
return response.data;
}
Продвинутые техники для серверных задач
// Система мониторинга с интерсепторами
const monitoringAPI = axios.create({
baseURL: 'https://monitoring.example.com',
timeout: 15000
});
// Интерсептор для логирования всех запросов
monitoringAPI.interceptors.request.use(
config => {
console.log(`[${new Date().toISOString()}] ${config.method.toUpperCase()} ${config.url}`);
return config;
},
error => {
console.error('Request interceptor error:', error);
return Promise.reject(error);
}
);
// Интерсептор для автоматической повторной аутентификации
monitoringAPI.interceptors.response.use(
response => response,
async error => {
if (error.response?.status === 401) {
console.log('Token expired, refreshing...');
try {
const newToken = await refreshAuthToken();
error.config.headers.Authorization = `Bearer ${newToken}`;
return axios.request(error.config);
} catch (refreshError) {
console.error('Token refresh failed:', refreshError);
// Redirect to login or handle accordingly
}
}
return Promise.reject(error);
}
);
Обработка ошибок и таймаутов
Правильная обработка ошибок критически важна для серверных приложений:
// Комплексная обработка ошибок
async function robustAPICall(url, data = null) {
try {
const config = {
timeout: 10000,
retry: 3,
retryDelay: 1000
};
const response = await axios.post(url, data, config);
return response.data;
} catch (error) {
if (error.code === 'ECONNABORTED') {
console.error('Request timeout');
} else if (error.response) {
// Сервер ответил с ошибкой
console.error(`Server error: ${error.response.status} - ${error.response.data}`);
} else if (error.request) {
// Запрос был отправлен, но ответа нет
console.error('No response received');
} else {
// Ошибка в настройке запроса
console.error('Request setup error:', error.message);
}
throw error;
}
}
// Реализация retry-логики
async function withRetry(fn, maxRetries = 3, delay = 1000) {
for (let i = 0; i < maxRetries; i++) {
try {
return await fn();
} catch (error) {
if (i === maxRetries - 1) throw error;
console.log(`Retry ${i + 1}/${maxRetries} after ${delay}ms`);
await new Promise(resolve => setTimeout(resolve, delay));
delay *= 2; // Exponential backoff
}
}
}
Автоматизация и массовые операции
// Массовая проверка статуса серверов
async function checkServerHealth(serverList) {
const promises = serverList.map(server => {
return axios.get(`${server.url}/health`, {
timeout: 5000,
validateStatus: status => status < 500
}).then(response => ({
server: server.name,
status: 'healthy',
responseTime: response.headers['x-response-time']
})).catch(error => ({
server: server.name,
status: 'unhealthy',
error: error.message
}));
});
const results = await Promise.allSettled(promises);
return results.map(result => result.value);
}
// Отправка уведомлений в Slack/Discord
async function sendAlert(message, webhookUrl) {
try {
await axios.post(webhookUrl, {
text: message,
channel: '#alerts',
username: 'ServerBot'
});
} catch (error) {
console.error('Failed to send alert:', error.message);
}
}
// Автоматическое развертывание через API
async function deployService(serviceName, version) {
const deploymentData = {
service: serviceName,
version: version,
timestamp: new Date().toISOString()
};
try {
const response = await axios.post('/api/deploy', deploymentData, {
timeout: 60000, // Долгие операции требуют большего таймаута
headers: {
'X-Deploy-Token': process.env.DEPLOY_TOKEN
}
});
console.log(`Deployment started: ${response.data.deploymentId}`);
return response.data;
} catch (error) {
console.error('Deployment failed:', error.response?.data || error.message);
throw error;
}
}
Сравнение с альтернативными решениями
Характеристика | Axios | Fetch API | XMLHttpRequest | Node.js http |
---|---|---|---|---|
Размер библиотеки | ~45KB | Встроенный | Встроенный | Встроенный |
Поддержка промисов | ✅ Из коробки | ✅ Нативно | ❌ Нужен wrapper | ❌ Callbacks |
Автоматический JSON | ✅ Да | ❌ Ручное | ❌ Ручное | ❌ Ручное |
Интерсепторы | ✅ Да | ❌ Нет | ❌ Нет | ❌ Нет |
Отмена запросов | ✅ Да | ✅ AbortController | ✅ abort() | ✅ destroy() |
Поддержка таймаутов | ✅ Встроенная | ✅ С AbortController | ✅ timeout свойство | ✅ setTimeout |
Интеграция с другими инструментами
Axios отлично интегрируется с различными инструментами администрирования:
// Интеграция с PM2 для мониторинга процессов
const pm2 = require('pm2');
async function getProcessStats() {
return new Promise((resolve, reject) => {
pm2.list((err, processes) => {
if (err) reject(err);
const stats = processes.map(proc => ({
name: proc.name,
status: proc.pm2_env.status,
cpu: proc.cpu,
memory: proc.memory
}));
resolve(stats);
});
});
}
// Отправка метрик в Grafana/Prometheus
async function sendMetrics(metrics) {
try {
await axios.post('http://localhost:9090/api/v1/write', metrics, {
headers: {
'Content-Type': 'application/x-protobuf',
'X-Prometheus-Remote-Write-Version': '0.1.0'
}
});
} catch (error) {
console.error('Failed to send metrics:', error.message);
}
}
// Интеграция с Docker API
async function getContainerStats() {
try {
const response = await axios.get('http://localhost:2375/containers/json', {
params: { all: true }
});
return response.data.map(container => ({
id: container.Id.substring(0, 12),
name: container.Names[0],
status: container.State,
image: container.Image
}));
} catch (error) {
console.error('Docker API error:', error.message);
return [];
}
}
Продвинутые возможности и хитрости
// Создание пула соединений для высокой нагрузки
const https = require('https');
const http = require('http');
const httpsAgent = new https.Agent({
keepAlive: true,
maxSockets: 50
});
const httpAgent = new http.Agent({
keepAlive: true,
maxSockets: 50
});
const optimizedAxios = axios.create({
httpsAgent,
httpAgent,
timeout: 30000
});
// Кэширование запросов
const cache = new Map();
axios.interceptors.request.use(config => {
if (config.method === 'get') {
const cached = cache.get(config.url);
if (cached && Date.now() - cached.timestamp < 60000) {
return Promise.resolve(cached.data);
}
}
return config;
});
axios.interceptors.response.use(response => {
if (response.config.method === 'get') {
cache.set(response.config.url, {
data: response,
timestamp: Date.now()
});
}
return response;
});
// Middleware для rate limiting
class RateLimiter {
constructor(maxRequests = 100, timeWindow = 60000) {
this.maxRequests = maxRequests;
this.timeWindow = timeWindow;
this.requests = [];
}
async checkLimit() {
const now = Date.now();
this.requests = this.requests.filter(time => now - time < this.timeWindow);
if (this.requests.length >= this.maxRequests) {
const waitTime = this.timeWindow - (now - this.requests[0]);
await new Promise(resolve => setTimeout(resolve, waitTime));
}
this.requests.push(now);
}
}
const rateLimiter = new RateLimiter(10, 60000);
axios.interceptors.request.use(async config => {
await rateLimiter.checkLimit();
return config;
});
Практические скрипты для автоматизации
#!/usr/bin/env node
// Скрипт для автоматического бэкапа через API
const axios = require('axios');
const fs = require('fs');
const path = require('path');
async function createBackup() {
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
const backupName = `backup-${timestamp}`;
try {
console.log('Starting backup creation...');
// Инициация бэкапа
const { data } = await axios.post('/api/backup', {
name: backupName,
compression: 'gzip',
incremental: false
});
const backupId = data.id;
console.log(`Backup initiated: ${backupId}`);
// Ожидание завершения
let status = 'running';
while (status === 'running') {
await new Promise(resolve => setTimeout(resolve, 5000));
const statusResponse = await axios.get(`/api/backup/${backupId}/status`);
status = statusResponse.data.status;
console.log(`Backup status: ${status}`);
}
if (status === 'completed') {
// Скачивание бэкапа
const downloadResponse = await axios.get(`/api/backup/${backupId}/download`, {
responseType: 'stream'
});
const filePath = path.join(__dirname, 'backups', `${backupName}.tar.gz`);
const writer = fs.createWriteStream(filePath);
downloadResponse.data.pipe(writer);
return new Promise((resolve, reject) => {
writer.on('finish', () => {
console.log(`Backup saved: ${filePath}`);
resolve(filePath);
});
writer.on('error', reject);
});
} else {
throw new Error(`Backup failed with status: ${status}`);
}
} catch (error) {
console.error('Backup failed:', error.message);
process.exit(1);
}
}
// Запуск с обработкой ошибок
createBackup().catch(console.error);
Полезные факты и нестандартные применения
Axios можно использовать не только для REST API, но и для:
- GraphQL запросов — просто отправляйте POST с query в теле
- Работы с WebDAV — поддерживает методы PROPFIND, MKCOL и другие
- Тестирования API — интеграция с Jest, Mocha для автотестов
- Proxy-серверов — встроенная поддержка HTTP/HTTPS прокси
- Мониторинга SSL-сертификатов — проверка срока действия через HTTPS-запросы
Интересная статистика: согласно данным npm, Axios скачивается более 20 миллионов раз в неделю, что делает его одной из самых популярных JavaScript-библиотек. Библиотека активно развивается, с регулярными обновлениями безопасности.
Возможности для автоматизации и DevOps
Axios открывает множество возможностей для автоматизации:
- CI/CD интеграция — триггеры деплоя, проверка статуса сборки
- Мониторинг инфраструктуры — health checks, сбор метрик
- Автоматические бэкапы — по расписанию через cron
- Нотификации — интеграция с Slack, Telegram, email
- Управление конфигурацией — обновление настроек через API
Для развертывания таких автоматизированных решений идеально подходят VPS-серверы, которые предоставляют необходимые ресурсы и гибкость настройки. Если вам нужна платформа для экспериментов с API и автоматизацией, рекомендую присмотреться к аренде VPS для легких задач или выделенный сервер для более ресурсоемких проектов.
Заключение и рекомендации
Axios — это не просто HTTP-клиент, а мощный инструмент для построения надежных серверных приложений. Его преимущества особенно ярко проявляются при работе с микросервисами, API интеграциями и задачами автоматизации.
Рекомендации по использованию:
- Используйте экземпляры axios.create() для разных API с собственными настройками
- Всегда настраивайте timeout’ы для продакшн-среды
- Реализуйте retry-логику для критичных запросов
- Используйте интерсепторы для централизованного логирования и обработки ошибок
- Не забывайте про rate limiting при работе с внешними API
- Кэшируйте результаты GET-запросов там, где это уместно
Axios подходит для любых задач — от простых скриптов мониторинга до сложных систем оркестрации. Его надежность и богатый функционал делают его незаменимым инструментом в арсенале любого системного администратора или DevOps-инженера.
Полезные ссылки для дальнейшего изучения:
В этой статье собрана информация и материалы из различных интернет-источников. Мы признаем и ценим работу всех оригинальных авторов, издателей и веб-сайтов. Несмотря на то, что были приложены все усилия для надлежащего указания исходного материала, любая непреднамеренная оплошность или упущение не являются нарушением авторских прав. Все упомянутые товарные знаки, логотипы и изображения являются собственностью соответствующих владельцев. Если вы считаете, что какой-либо контент, использованный в этой статье, нарушает ваши авторские права, немедленно свяжитесь с нами для рассмотрения и принятия оперативных мер.
Данная статья предназначена исключительно для ознакомительных и образовательных целей и не ущемляет права правообладателей. Если какой-либо материал, защищенный авторским правом, был использован без должного упоминания или с нарушением законов об авторском праве, это непреднамеренно, и мы исправим это незамедлительно после уведомления. Обратите внимание, что переиздание, распространение или воспроизведение части или всего содержимого в любой форме запрещено без письменного разрешения автора и владельца веб-сайта. Для получения разрешений или дополнительных запросов, пожалуйста, свяжитесь с нами.