はじめに
JavaScriptで fetch 関数を使用して、複数のAPIへのリクエストを並行(同時)実行、または依存関係がある場合に順次(直列)実行する際の現代的なベストプラクティス(async/await 構文)をまとめます。
主に以下の2パターンを扱います。
-
並行(同時)実行: 各APIが独立しており、同時にリクエストを発行して高速化したい場合(
Promise.all/Promise.allSettled) -
順次(直列)実行: 最初のAPI実行結果を次のAPIのリクエストパラメータで利用する場合(
async/await)
1. 複数APIの並行(同時)実行
全件の取得成功が必要な場合(Promise.all)
全APIのリクエストを同時に発行し、すべてのレスポンスとJSON解析が完了するのを待機します。
async function fetchAllData() {
const urls = [
"https://api.example.com/users",
"https://api.example.com/products",
];
try {
// 1. 全APIへのリクエストを並行して発行
const responses = await Promise.all(urls.map((url) => fetch(url)));
// 2. HTTPエラーのチェック
for (const res of responses) {
if (!res.ok) {
throw new Error(`HTTP error! status: ${res.status}`);
}
}
// 3. 全レスポンスのJSON解析を並行して実行
const [users, products] = await Promise.all(
responses.map((res) => res.json()),
);
return { users, products };
} catch (error) {
console.error("APIの同時取得中にエラーが発生しました:", error);
throw error;
}
}
一部のAPI失敗を許容する場合(Promise.allSettled)
一部のAPIが失敗しても全滅させず、成功したレスポンスデータのみを取り出したい場合は Promise.allSettled を使用します。
async function fetchWithPartialFailure() {
const urls = [
"https://api.example.com/main-data",
"https://api.example.com/optional-data",
];
// 各fetchのJSON化まで含めたPromise配列を作成
const promises = urls.map(async (url) => {
const res = await fetch(url);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return res.json();
});
// 全件の結末(成功 or 失敗)を待機
const results = await Promise.allSettled(promises);
const successfulData = results
.filter((result) => result.status === "fulfilled")
.map((result) => result.value);
return successfulData;
}
2. 依存関係がある場合の順次(直列)実行
最初のAPI実行結果を、次のAPIのURLやリクエストボディ・ヘッダーで使用する場合は、await を使って可読性の高い直列処理を記述します。
async function fetchSequentialData() {
try {
// 1st API: ユーザー情報を取得
const userRes = await fetch("https://api.example.com/user/me");
if (!userRes.ok) throw new Error("ユーザー情報の取得に失敗しました");
const user = await userRes.json();
// 2nd API: 取得したユーザーIDを使って投稿一覧を取得
const postsRes = await fetch(
`https://api.example.com/posts?userId=${user.id}`,
);
if (!postsRes.ok) throw new Error("投稿一覧の取得に失敗しました");
const posts = await postsRes.json();
return { user, posts };
} catch (error) {
console.error("順次API実行エラー:", error);
throw error;
}
}
まとめ
- 互いに影響しない複数APIの取得は
Promise.all(またはPromise.allSettled)で並行実行するのが最も高速です。 - 前のAPI結果を後ろのAPIで利用する場合は
async/awaitを使用した直列処理を記述することで、コールバック地獄を防ぎシンプルに実装できます。