5
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

複数APIへのリクエストをfetch関数で同時実行するプラクティス

5
Last updated at Posted at 2021-09-05

はじめに

JavaScriptで fetch 関数を使用して、複数のAPIへのリクエストを並行(同時)実行、または依存関係がある場合に順次(直列)実行する際の現代的なベストプラクティス(async/await 構文)をまとめます。

主に以下の2パターンを扱います。

  1. 並行(同時)実行: 各APIが独立しており、同時にリクエストを発行して高速化したい場合(Promise.all / Promise.allSettled
  2. 順次(直列)実行: 最初の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 を使用した直列処理を記述することで、コールバック地獄を防ぎシンプルに実装できます。

参考

5
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?