📦معرفی و مقایسه با Fetch

Axios یک کتابخانه Promise-based برای ارسال درخواست‌های HTTP است که هم در مرورگر (بر پایه XMLHttpRequest) و هم در Node.js (بر پایه http module) کار می‌کند.

Axios در مقابل Fetch API

ویژگیAxiosFetch API
Parse JSONخودکارنیاز به .json()
مدیریت خطای HTTP4xx/5xx → rejectفقط خطای شبکه
Timeoutداخلینیاز به AbortController
Interceptorsداردندارد
Upload ProgressonUploadProgressندارد
XSRF Protectionداخلیدستی
Request/Response Transformداردندارد
Node.js SupportبلهNode 18+
حجم~۳۲KBداخلی مرورگر

نصب

<!-- روش ۱: فایل لوکال -->
<script src="axios.min.js"></script>

<!-- روش ۲: CDN -->
<script src="https://cdn.jsdelivr.net/npm/axios@1.6.8/dist/axios.min.js"></script>

/* روش ۳: NPM */
// npm install axios
import axios from 'axios';

ساختار Response

// هر پاسخ موفق Axios یک آبجکت با این فیلدها دارد:
{
  data:       {},       // ← JSON به‌صورت خودکار parse شده
  status:     200,      // کد HTTP
  statusText: 'OK',    // متن وضعیت
  headers:    {},       // هدرهای پاسخ
  config:     {},       // تنظیمات درخواست
  request:    {}        // آبجکت XMLHttpRequest
}

متدهای اصلی

متدHTTPکاربرد
axios.get(url, config?)GETدریافت داده
axios.post(url, data, config?)POSTایجاد رکورد جدید
axios.put(url, data, config?)PUTجایگزینی کامل
axios.patch(url, data, config?)PATCHبروزرسانی جزئی
axios.delete(url, config?)DELETEحذف رکورد
axios(config)همهدرخواست کاملاً سفارشی
ⓘ درباره دموها: تمام دموهای این صفحه از API عمومی JSONPlaceholder (jsonplaceholder.typicode.com) استفاده می‌کنند. برای اجرای دموها به اینترنت نیاز دارید.

📥درخواست GET GET

GET برای دریافت داده از سرور استفاده می‌شود. پارامترهای query string را با params پاس دهید.

GET پایه

// Promise chain
axios.get('https://jsonplaceholder.typicode.com/posts/1')
  .then(res => {
    console.log(res.data);       // JSON parse شده
    console.log(res.status);     // 200
  })
  .catch(err => console.error(err.message));

GET با Query Parameters

// Axios به‌صورت خودکار params را به ?key=val تبدیل می‌کند
axios.get('https://jsonplaceholder.typicode.com/posts', {
  params: {
    userId: 1,   // ?userId=1
    _limit: 5    // &_limit=5
  }
}).then(res => console.log(res.data));
// URL نهایی: /posts?userId=1&_limit=5

درخواست‌های موازی

// Promise.all — همه موازی اجرا می‌شوند
const [postRes, userRes] = await Promise.all([
  axios.get('/posts/1'),
  axios.get('/users/1')
]);
console.log(postRes.data, userRes.data);

// axios.all + axios.spread (روش قدیمی‌تر)
axios.all([req1, req2])
  .then(axios.spread((res1, res2) => { /* ... */ }));
▶ دمو: درخواست‌های GET زنده
// نتیجه اینجا نمایش داده می‌شود...

📤POST / PUT / PATCH / DELETE POST PUT PATCH DELETE

POST — ایجاد رکورد

Axios به‌صورت خودکار object را به JSON تبدیل و هدر Content-Type: application/json را تنظیم می‌کند:

axios.post('https://jsonplaceholder.typicode.com/posts', {
  title:  'عنوان پست جدید',
  body:   'متن کامل پست',
  userId: 1
}).then(res => {
  console.log(res.status);   // 201 Created
  console.log(res.data.id);  // ID رکورد جدید
});

PUT و PATCH

// PUT: جایگزینی کامل رکورد
axios.put('/posts/1', {
  id: 1, title: 'عنوان جدید', body: 'متن جدید', userId: 1
});

// PATCH: فقط فیلدهای مشخص شده آپدیت می‌شوند
axios.patch('/posts/1', {
  title: 'فقط عنوان تغییر می‌کند'
});

DELETE

axios.delete('/posts/1')
  .then(res => console.log('حذف شد — status:', res.status)); // 200

درخواست سفارشی با config کامل

// روش عمومی — برای کنترل کامل
axios({
  method:  'post',
  url:     '/api/posts',
  data:    { title: '...' },
  headers: { 'Authorization': 'Bearer token' },
  timeout: 5000,
  params:  { source: 'web' }
});
▶ دمو: CRUD زنده
// نتیجه اینجا...

🔐هدرها، احراز هویت و Timeout

هدرهای یک درخواست

axios.get('/api/profile', {
  headers: {
    'Authorization': `Bearer ${token}`,
    'Accept-Language': 'fa',
    'X-Request-ID':    'uuid-1234'
  }
});

هدرهای سراسری

// برای همه درخواست‌ها
axios.defaults.headers.common['Authorization'] = 'Bearer ' + token;
axios.defaults.baseURL = 'https://api.mysite.com/v1';
axios.defaults.timeout = 10000;

// فقط برای POST/PUT
axios.defaults.headers.post['Content-Type'] = 'application/json';

Timeout

axios.get('/api/slow', { timeout: 5000 }) // ۵ ثانیه
  .catch(err => {
    if (err.code === 'ECONNABORTED') {
      console.log('⏱ درخواست به timeout رسید');
    }
  });

Basic Authentication

// روش ۱: با auth object
axios.get('/api/data', {
  auth: { username: 'user', password: 'pass' }
});
// هدر Authorization: Basic dXNlcjpwYXNz را اضافه می‌کند

// روش ۲: توکن JWT
axios.get('/api/data', {
  headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}` }
});
▶ دمو: هدر سفارشی و Timeout
// نتیجه اینجا...

🔄Interceptorها

Interceptorها یکی از قدرتمندترین قابلیت‌های Axios هستند. کد را قبل از ارسال درخواست یا بعد از دریافت پاسخ اجرا می‌کنند — بدون تکرار در هر call.

ⓘ کاربردهای اصلی: افزودن توکن به همه درخواست‌ها، نمایش spinner، refresh خودکار توکن، لاگ درخواست‌ها، نمایش پیام خطا.

Request و Response Interceptor

// ── Interceptor درخواست ──
axios.interceptors.request.use(
  config => {
    // قبل از ارسال هر درخواست
    const token = localStorage.getItem('token');
    if (token) config.headers.Authorization = `Bearer ${token}`;
    config.metadata = { startTime: new Date() };
    return config;  // ← حتماً config را برگردانید
  },
  error => Promise.reject(error)
);

// ── Interceptor پاسخ ──
axios.interceptors.response.use(
  response => {
    // هر پاسخ موفق (2xx)
    const elapsed = new Date() - response.config.metadata?.startTime;
    console.log(`✅ ${response.status} — ${elapsed}ms`);
    return response;
  },
  error => {
    // هر پاسخ خطا
    if (error.response?.status === 401) {
      // توکن منقضی — هدایت به صفحه ورود
      window.location.href = '/login';
    }
    if (error.response?.status === 429) {
      // Rate limit — می‌توان retry کرد
      console.log('⚠️ Rate limit — دوباره تلاش کنید');
    }
    return Promise.reject(error);
  }
);

حذف Interceptor

const id = axios.interceptors.request.use(config => config);
axios.interceptors.request.eject(id); // حذف

Retry Interceptor — تلاش مجدد خودکار

// تلاش مجدد خودکار در صورت خطای شبکه یا ۵xx
axios.interceptors.response.use(null, async error => {
  const config = error.config;
  if (!config || config._retryCount >= 3) return Promise.reject(error);

  const shouldRetry =
    !error.response ||                          // خطای شبکه
    error.response.status >= 500;              // خطای سرور

  if (!shouldRetry) return Promise.reject(error);

  config._retryCount = (config._retryCount || 0) + 1;
  const delay = 1000 * config._retryCount; // 1s, 2s, 3s
  await new Promise(r => setTimeout(r, delay));
  console.log(`🔄 تلاش ${config._retryCount}/3...`);
  return axios(config);
});
▶ دمو: Interceptor با لاگ زنده
// لاگ interceptor اینجا نمایش داده می‌شود...

مدیریت خطاها

Axios هر کد HTTP خارج از محدوده 2xx را به‌عنوان خطا reject می‌کند. آبجکت خطا سه ساختار مختلف دارد:

try {
  await axios.get('/api/data');
} catch (error) {
  if (error.response) {
    // سرور پاسخ داد — کد خطا (4xx یا 5xx)
    console.log(error.response.status);   // 404, 403, 500 ...
    console.log(error.response.data);     // body پاسخ خطا
    console.log(error.response.headers);  // هدرهای پاسخ

  } else if (error.request) {
    // درخواست ارسال شد ولی پاسخ نرسید (مشکل شبکه / CORS)
    console.log('Network Error', error.request);

  } else {
    // خطا در ساختن درخواست
    console.log('Config Error:', error.message);
  }

  // بررسی timeout
  if (error.code === 'ECONNABORTED') console.log('⏱ Timeout!');

  // بررسی cancel
  if (axios.isCancel(error)) console.log('درخواست لغو شد');
}

جدول خطاها

خطادلیلشناسایی
400 Bad Requestداده نامعتبرstatus === 400
401 Unauthorizedتوکن نامعتبر/منقضیstatus === 401
403 Forbiddenعدم دسترسیstatus === 403
404 Not Foundمنبع پیدا نشدstatus === 404
422 UnprocessableValidation Errorstatus === 422
429 Too Many RequestsRate Limitstatus === 429
500+ Server Errorخطای داخلی سرورstatus >= 500
Network Errorقطعی شبکه / CORS!error.response
Timeoutزمان انتظار تمام شدerror.code === 'ECONNABORTED'
Cancelledلغو توسط برنامهaxios.isCancel(error)
▶ دمو: مدیریت خطاها
// نتیجه اینجا...

async/await و axios.create

الگوی async/await

async function getUser(id) {
  try {
    const { data } = await axios.get(`/users/${id}`);
    // ← destructuring مستقیم data
    return data;
  } catch (error) {
    if (error.response?.status === 404) return null;
    throw error;
  }
}

// await روی چند درخواست موازی
const [users, posts] = await Promise.all([
  axios.get('/users').then(r => r.data),
  axios.get('/posts').then(r => r.data),
]);

axios.create() — Instance اختصاصی

// ── api.js ──
const api = axios.create({
  baseURL: 'https://api.mysite.com/v1',
  timeout: 10000,
  headers: {
    'Content-Type': 'application/json',
    'X-App-Version': '2.0.0'
  }
});

// Interceptor روی instance اختصاصی
api.interceptors.request.use(config => {
  config.headers.Authorization = `Bearer ${getToken()}`;
  return config;
});

// استفاده در همه جا — بدون تکرار تنظیمات
api.get('/users');
api.post('/posts', data);
api.delete(`/comments/${id}`);
💡 چرا axios.create مهم است؟ اگر چند API مختلف (با baseURL های متفاوت) دارید، برای هر کدام یک instance جداگانه بسازید. هر instance interceptorها و تنظیمات مستقل خود را دارد.
▶ دمو: async/await و axios.create
// نتیجه اینجا...

📤آپلود فایل با Progress

Axios از طریق onUploadProgress و onDownloadProgress امکان نمایش پیشرفت آپلود/دانلود را فراهم می‌کند. این ویژگی در Fetch API وجود ندارد.

آپلود فایل

const formData = new FormData();
formData.append('file', fileInput.files[0]);
formData.append('name', 'profile-photo');

axios.post('/api/upload', formData, {
  headers: { 'Content-Type': 'multipart/form-data' },

  onUploadProgress: progressEvent => {
    const percent = Math.round(
      (progressEvent.loaded / progressEvent.total) * 100
    );
    progressBar.style.width = percent + '%';
    label.textContent = percent + '% آپلود شد';
  }
});

دانلود با Progress

axios.get('/api/large-file', {
  responseType: 'blob',
  onDownloadProgress: e => {
    if (e.total) {
      const pct = Math.round((e.loaded / e.total) * 100);
      progressBar.style.width = pct + '%';
    }
  }
}).then(res => {
  // ذخیره فایل دانلود شده
  const url  = URL.createObjectURL(res.data);
  const link = document.createElement('a');
  link.href = url; link.download = 'file.pdf'; link.click();
});
▶ دمو: شبیه‌سازی آپلود با Progress
پیشرفت آپلود 0%
آماده آپلود

لغو درخواست (Cancel Request)

گاهی نیاز دارید یک درخواست در حال اجرا را لغو کنید — مثلاً وقتی کاربر از صفحه خارج می‌شود یا یک جستجوی جدید می‌زند. Axios از AbortController پشتیبانی می‌کند.

روش AbortController (مدرن — توصیه‌شده)

const controller = new AbortController();

// ارسال درخواست با signal
axios.get('/api/data', {
  signal: controller.signal
})
.then(res => console.log(res.data))
.catch(err => {
  if (axios.isCancel(err)) {
    console.log('درخواست لغو شد:', err.message);
  }
});

// لغو (هر زمان)
controller.abort('کاربر از صفحه خارج شد');

الگوی لغو در جستجو (Search Debounce)

let controller;

searchInput.addEventListener('input', async (e) => {
  // لغو درخواست قبلی قبل از ارسال جدید
  if (controller) controller.abort();
  controller = new AbortController();

  try {
    const { data } = await axios.get('/api/search', {
      params: { q: e.target.value },
      signal: controller.signal
    });
    renderResults(data);
  } catch (err) {
    if (!axios.isCancel(err)) console.error(err);
    // خطاهای cancel را نادیده می‌گیریم
  }
});

لغو در React useEffect

useEffect(() => {
  const controller = new AbortController();

  axios.get(`/api/user/${userId}`, { signal: controller.signal })
    .then(res => setUser(res.data))
    .catch(err => { if (!axios.isCancel(err)) setError(err); });

  return () => controller.abort(); // ← cleanup هنگام unmount
}, [userId]);
▶ دمو: لغو درخواست در حال اجرا
// درخواست را شروع کنید سپس لغو کنید...

🌟معماری سرویس واقعی

در پروژه‌های واقعی، درخواست‌های HTTP را در فایل‌های سرویس جداگانه سازماندهی کنید. این الگو کد را قابل نگهداری، تست‌پذیر و DRY نگه می‌دارد.

فایل api.js — پایه

// src/api/api.js
const api = axios.create({
  baseURL: process.env.REACT_APP_API_URL || 'https://api.mysite.com/v1',
  timeout: 15000,
  headers: { 'Content-Type': 'application/json' }
});

// افزودن توکن به همه درخواست‌ها
api.interceptors.request.use(config => {
  const token = localStorage.getItem('access_token');
  if (token) config.headers.Authorization = `Bearer ${token}`;
  return config;
});

// مدیریت خطا و refresh توکن
api.interceptors.response.use(
  res => res,
  async err => {
    if (err.response?.status === 401 && !err.config._retry) {
      err.config._retry = true;
      try {
        const { data } = await axios.post('/auth/refresh', {
          refreshToken: localStorage.getItem('refresh_token')
        });
        localStorage.setItem('access_token', data.token);
        err.config.headers.Authorization = `Bearer ${data.token}`;
        return api(err.config); // ← retry با توکن جدید
      } catch { window.location.href = '/login'; }
    }
    return Promise.reject(err);
  }
);

export default api;

سرویس‌های اختصاصی

// src/services/userService.js
import api from '../api/api';

export const userService = {
  getAll: (params = {}) => api.get('/users', { params }),
  getById: id         => api.get(`/users/${id}`),
  create: data        => api.post('/users', data),
  update: (id, data)  => api.put(`/users/${id}`, data),
  patch:  (id, data)  => api.patch(`/users/${id}`, data),
  remove: id          => api.delete(`/users/${id}`),
  upload: (id, file, onProgress) => {
    const fd = new FormData();
    fd.append('avatar', file);
    return api.post(`/users/${id}/avatar`, fd, {
      headers: { 'Content-Type': 'multipart/form-data' },
      onUploadProgress: e => onProgress?.(Math.round(e.loaded/e.total*100))
    });
  }
};

// استفاده در component
const users = await userService.getAll({ page: 1, limit: 20 });
await userService.update(5, { name: 'نام جدید' });
▶ دمو: سرویس کامل با axios.create
// نتیجه سرویس اینجا...
💡 چک‌لیست پروژه واقعی:
  • یک api.js با axios.create() بسازید
  • توکن را در request interceptor اضافه کنید
  • refresh توکن را در response interceptor پیاده کنید
  • برای هر منبع یک فایل سرویس جداگانه بسازید
  • AbortController را در componentهای React cleanup کنید
  • در محیط تولید، timeout معقول تنظیم کنید
🔗 axios-http.com 📚 GitHub: axios/axios ★ 104k+ stars 🔌 MIT License 📱 Browser + Node.js

🚀زمین بازی کد (Playground)

کد Axios را همین‌جا اجرا کن و خروجی را در کنسول پایین ببین. چون محیط آفلاین است، یک adapter ساختگی پاسخ سرور را شبیه‌سازی می‌کند تا روی الگوی واقعی Axios (GET/POST، async/await، Interceptor) تمرین کنی.

💡 خروجی console.log() در پنل پایینِ پیش‌نمایش نمایش داده می‌شود. نسخهٔ ۱.۶.۸ همین صفحه آفلاین بارگذاری می‌شود.