Axios
JavaScript/TypeScript向けの最も人気のHTTPクライアントライブラリ。プロミスベースAPI、リクエスト・レスポンス変換、自動JSON処理、インターセプター、エラーハンドリング、タイムアウト機能を提供。ブラウザとNode.js両環境で動作し、豊富な設定オプションを持つ。
GitHub概要
スター107,980
ウォッチ1,180
フォーク11,350
作成日:2014年8月18日
言語:JavaScript
ライセンス:MIT License
トピックス
hacktoberfesthttp-clientjavascriptnodejspromise
スター履歴
データ取得日時: 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);