Axios

TypeScript/JavaScript向けの最も人気のHTTPクライアントライブラリ。完全なTypeScriptサポート、プロミスベースAPI、リクエスト・レスポンス変換、自動JSON処理、インターセプター、エラーハンドリング機能を提供。型安全性と豊富な機能で開発効率を向上。

HTTPクライアントJavaScriptTypeScriptNode.jsWeb APIPromise

GitHub概要

axios/axios

Promise based HTTP client for the browser and node.js

ホームページ:https://axios-http.com
スター107,980
ウォッチ1,180
フォーク11,350
作成日:2014年8月18日
言語:JavaScript
ライセンス:MIT License

トピックス

hacktoberfesthttp-clientjavascriptnodejspromise

スター履歴

axios/axios Star History
データ取得日時: 2025/10/22 04:10

ライブラリ

Axios

概要

Axiosは「Promise based HTTP client for the browser and node.js」として開発されたHTTPクライアントライブラリです。ブラウザとNode.js環境の両方で同一のコードベースで動作するアイソモルフィック設計で、サーバーサイドではnative Node.js HTTPモジュールを、クライアントサイドではXMLHttpRequestsを使用します。自動的なJSON変換、リクエスト・レスポンスインターセプター、堅牢なエラーハンドリングを提供し、IE11を含む古いブラウザまでサポートします。

詳細

Axios 1.7.9は2025年現在も活発に開発されているJavaScript界で最も人気の高いHTTPクライアントライブラリです。TypeScript 4.7以上での完全なTypeScriptサポートと、esModuleInteropによる柔軟なモジュール解決を提供。自動的なJSON変換により手動パースの必要がなく、グローバルインターセプターによりリクエストやレスポンスの統一的な前処理・後処理が可能。XMLHttpRequestベースによりIE11を含む古いブラウザでも動作します。

主な特徴

  • 自動JSON変換: JSONレスポンスの自動的なJavaScriptオブジェクトへの変換
  • インターセプター: リクエスト・レスポンスのグローバルな前処理・後処理機能
  • デフォルト設定: ベースURLやヘッダーなどの事前定義設定によるコード重複削減
  • エラーハンドリング: 詳細なエラーメッセージによる堅牢なエラーハンドリング
  • 幅広いブラウザサポート: IE11を含む古いブラウザでの安定動作
  • TypeScript統合: TypeScript定義とエラータイプガードの内蔵

メリット・デメリット

メリット

  • JavaScript界で最も歴史と実績のあるHTTPクライアント(10年以上の開発実績)
  • IE11を含む幅広いブラウザサポートによる高い互換性
  • 自動JSON変換と豊富な設定オプションによる開発効率向上
  • インターセプターによる統一的なリクエスト・レスポンス処理
  • 堅牢なエラーハンドリングとデバッグの容易さ
  • 充実したエコシステムとプラグイン、拡張機能

デメリット

  • バンドルサイズが35KB追加される(Fetch APIは0KB)
  • モダンブラウザではFetch APIで同等機能を実現可能
  • 軽量なAPIクライアントが必要な場合はオーバースペック
  • XMLHttpRequestベースのため一部の新機能が制限される
  • 多機能ゆえの設定の複雑さ
  • fetch APIに比べて学習コストがやや高い

参考ページ

書き方の例

基本的なセットアップ

# Axiosのインストール
npm install axios

# TypeScript用の型定義(通常は自動的に含まれる)
# npm install @types/axios  # 最新版では不要

インポートとベーシックな使用

// ES6モジュール(推奨)
import axios from 'axios';

// CommonJS(Node.js)- TypeScript型サポート付き
const axios = require('axios').default;

// シンプルなGETリクエスト
axios.get('/user?ID=12345')
  .then(function (response) {
    // 成功時の処理
    console.log(response.data);
    console.log(response.status);
    console.log(response.headers);
  })
  .catch(function (error) {
    // エラー時の処理
    console.log(error);
  })
  .finally(function () {
    // 常に実行される処理
  });

// パラメータを別途指定する方法
axios.get('/user', {
    params: {
      ID: 12345
    }
  })
  .then(function (response) {
    console.log(response.data);
  })
  .catch(function (error) {
    console.log(error);
  });

Async/Awaitを使用した現代的なアプローチ

// async/awaitでの使用
async function getUser() {
  try {
    const response = await axios.get('/user?ID=12345');
    console.log('ユーザーデータ:', response.data);
    console.log('ステータス:', response.status);
    return response.data;
  } catch (error) {
    console.error('エラーが発生しました:', error);
    throw error;
  }
}

// POSTリクエストの例
async function createUser(userData) {
  try {
    const response = await axios.post('/user', {
      firstName: '太郎',
      lastName: '田中',
      email: '[email protected]'
    });
    console.log('ユーザー作成成功:', response.data);
    return response.data;
  } catch (error) {
    console.error('ユーザー作成エラー:', error);
    throw error;
  }
}

// 複数の同時リクエスト
async function getUserWithPermissions(userId) {
  try {
    const [userResponse, permissionsResponse] = await Promise.all([
      axios.get(`/user/${userId}`),
      axios.get(`/user/${userId}/permissions`)
    ]);
    
    return {
      user: userResponse.data,
      permissions: permissionsResponse.data
    };
  } catch (error) {
    console.error('データ取得エラー:', error);
    throw error;
  }
}

インスタンス作成とカスタム設定

// カスタムインスタンスの作成
const apiClient = axios.create({
  baseURL: 'https://api.example.com/v1',
  timeout: 10000,
  headers: {
    'Content-Type': 'application/json',
    'X-API-Key': 'your-api-key'
  }
});

// グローバルデフォルト設定
axios.defaults.baseURL = 'https://api.example.com';
axios.defaults.headers.common['Authorization'] = 'Bearer your-token';
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';

// 設定の優先順位テスト
const instance = axios.create();
instance.defaults.timeout = 2500; // インスタンスデフォルト

// リクエスト固有の設定(最優先)
instance.get('/longRequest', {
  timeout: 5000
});

// 完全な設定オプション例
const config = {
  url: '/user',
  method: 'get',
  baseURL: 'https://api.example.com',
  headers: {'X-Requested-With': 'XMLHttpRequest'},
  params: { ID: 12345 },
  data: { firstName: 'Fred' },
  timeout: 1000,
  withCredentials: false,
  auth: {
    username: 'janedoe',
    password: 's00pers3cret'
  },
  responseType: 'json',
  validateStatus: function (status) {
    return status >= 200 && status < 300;
  }
};

axios(config)
  .then(function (response) {
    console.log(response);
  });

インターセプターによる共通処理

// リクエストインターセプター
axios.interceptors.request.use(
  function (config) {
    // リクエスト送信前の処理
    console.log('リクエスト送信:', config);
    
    // 認証トークンの自動追加
    const token = localStorage.getItem('authToken');
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }
    
    // リクエスト時刻の記録
    config.metadata = { startTime: new Date() };
    
    return config;
  },
  function (error) {
    // リクエストエラー時の処理
    console.error('リクエストエラー:', error);
    return Promise.reject(error);
  }
);

// レスポンスインターセプター
axios.interceptors.response.use(
  function (response) {
    // ステータスコード2xxの場合の処理
    console.log('レスポンス受信:', response);
    
    // レスポンス時間の計算
    const endTime = new Date();
    const duration = endTime - response.config.metadata.startTime;
    console.log(`リクエスト所要時間: ${duration}ms`);
    
    return response;
  },
  function (error) {
    // ステータスコードがエラー範囲の場合の処理
    console.error('レスポンスエラー:', error);
    
    if (error.response.status === 401) {
      // 認証エラーの場合はログイン画面にリダイレクト
      localStorage.removeItem('authToken');
      window.location.href = '/login';
    }
    
    return Promise.reject(error);
  }
);

// インターセプターの削除
const myInterceptor = axios.interceptors.request.use(function () {/*...*/});
axios.interceptors.request.eject(myInterceptor);

エラーハンドリングとデバッグ

// 詳細なエラーハンドリング
axios.get('/user/12345')
  .catch(function (error) {
    if (error.response) {
      // サーバーが2xx以外のステータスコードで応答
      console.log('エラーデータ:', error.response.data);
      console.log('ステータス:', error.response.status);
      console.log('ヘッダー:', error.response.headers);
      
      // ステータスコード別処理
      switch (error.response.status) {
        case 400:
          console.error('バッドリクエスト: リクエストが無効です');
          break;
        case 401:
          console.error('認証エラー: ログインが必要です');
          break;
        case 404:
          console.error('リソースが見つかりません');
          break;
        case 500:
          console.error('サーバーエラーが発生しました');
          break;
        default:
          console.error('予期しないエラーが発生しました');
      }
    } else if (error.request) {
      // リクエストは送信されたがレスポンスを受信できなかった
      console.log('ネットワークエラー:', error.request);
      console.error('サーバーに接続できません');
    } else {
      // リクエスト設定時にエラーが発生
      console.log('設定エラー:', error.message);
    }
    
    // リクエスト設定情報
    console.log('リクエスト設定:', error.config);
    
    // 詳細なエラー情報(JSON形式)
    console.log('詳細エラー情報:', error.toJSON());
  });

// カスタムエラー判定
axios.get('/user/12345', {
  validateStatus: function (status) {
    return status < 500; // 500未満のステータスコードのみ成功とみなす
  }
});

// タイムアウトとリトライ機能の実装
async function requestWithRetry(config, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      const response = await axios(config);
      return response;
    } catch (error) {
      console.log(`試行 ${i + 1} 失敗:`, error.message);
      
      if (i === maxRetries - 1) {
        throw error; // 最後の試行で失敗した場合はエラーを投げる
      }
      
      // 指数バックオフで待機
      const delay = Math.pow(2, i) * 1000;
      await new Promise(resolve => setTimeout(resolve, delay));
    }
  }
}

// 使用例
try {
  const response = await requestWithRetry({
    url: '/api/unstable-endpoint',
    timeout: 5000
  });
  console.log('成功:', response.data);
} catch (error) {
  console.error('最終的に失敗:', error);
}

フォームデータとファイルアップロード

// FormDataの使用
const formData = new FormData();
formData.append('username', 'johndoe');
formData.append('email', '[email protected]');
formData.append('avatar', fileInput.files[0]);

axios.post('/user/upload', formData, {
  headers: {
    'Content-Type': 'multipart/form-data'
  },
  onUploadProgress: function (progressEvent) {
    const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total);
    console.log(`アップロード進捗: ${percentCompleted}%`);
  }
})
.then(function (response) {
  console.log('アップロード成功:', response.data);
});

// URL-encodedデータの送信
const params = new URLSearchParams();
params.append('name', 'John Doe');
params.append('email', '[email protected]');

axios.post('/user', params, {
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded'
  }
});

// FormDataヘッダーの自動設定インターセプター
axios.interceptors.request.use(config => {
  if (config.data instanceof FormData) {
    Object.assign(config.headers, config.data.getHeaders());
  }
  return config;
});

// ファイルダウンロード
async function downloadFile(url, filename) {
  try {
    const response = await axios({
      method: 'GET',
      url: url,
      responseType: 'blob',
      onDownloadProgress: function (progressEvent) {
        const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total);
        console.log(`ダウンロード進捗: ${percentCompleted}%`);
      }
    });

    // ブラウザでファイルをダウンロード
    const url_blob = window.URL.createObjectURL(new Blob([response.data]));
    const link = document.createElement('a');
    link.href = url_blob;
    link.setAttribute('download', filename);
    document.body.appendChild(link);
    link.click();
    link.remove();
    
    console.log('ダウンロード完了');
  } catch (error) {
    console.error('ダウンロードエラー:', error);
  }
}

リクエストキャンセレーション

// AbortController を使用したキャンセレーション(推奨)
const controller = new AbortController();

axios.get('/user/12345', {
  signal: controller.signal
})
.then(function (response) {
  console.log(response.data);
})
.catch(function (error) {
  if (axios.isCancel(error)) {
    console.log('リクエストがキャンセルされました:', error.message);
  } else {
    console.error('エラー:', error);
  }
});

// 5秒後にリクエストをキャンセル
setTimeout(() => {
  controller.abort('操作がタイムアウトしました');
}, 5000);

// 非推奨のCancelTokenを使用する方法(後方互換性のため)
const CancelToken = axios.CancelToken;
const source = CancelToken.source();

axios.get('/user/12345', {
  cancelToken: source.token
})
.catch(function (thrown) {
  if (axios.isCancel(thrown)) {
    console.log('リクエストキャンセル:', thrown.message);
  } else {
    console.error('エラー:', thrown);
  }
});

// キャンセル実行
source.cancel('ユーザーによってキャンセルされました');

// 複数リクエストの一括キャンセル
const cancelTokenSource = axios.CancelToken.source();

Promise.all([
  axios.get('/user/12345', { cancelToken: cancelTokenSource.token }),
  axios.get('/user/12345/permissions', { cancelToken: cancelTokenSource.token })
])
.then(function (responses) {
  console.log('全ての結果:', responses);
})
.catch(function (error) {
  if (axios.isCancel(error)) {
    console.log('全リクエストがキャンセルされました');
  }
});

// 条件に応じてキャンセル
setTimeout(() => {
  cancelTokenSource.cancel('操作がキャンセルされました');
}, 3000);