JavaScript | 複数の fetch を並列で実行 → どれか失敗しても安全に処理を続ける

JavaScript JavaScript
スポンサーリンク

ここでは、複数の fetch を並列で実行して、どれか1つ失敗しても他を続行できる安全な書き方 を、初心者向けに丁寧に解説します。


目的

複数のAPIを同時に呼び出すとき、

  • 1つでも失敗すると全部が止まる 😱(=悪い例)
  • 失敗したものだけスキップし、成功したものは処理を続ける ✅(=良い例)

この違いを理解するのが目的です。


❌ 悪い例:Promise.all(全部成功しないと失敗する)

// 悪い例:どれか1つでも失敗すると、全体が失敗する
async function loadAllData() {
  try {
    const urls = [
      'https://jsonplaceholder.typicode.com/posts/1',
      'https://jsonplaceholder.typicode.com/posts/9999999', // ← 存在しない
      'https://jsonplaceholder.typicode.com/posts/3'
    ];

    // Promise.all は「全部成功」が前提
    const responses = await Promise.all(urls.map(url => fetch(url)));

    const data = await Promise.all(responses.map(r => r.json()));
    console.log('すべて取得成功:', data);
  } catch (error) {
    console.error('どれか1つでも失敗 → 全体が失敗:', error);
  }
}

loadAllData();
JavaScript

🔍 結果

  • 2番目の fetch が 404 でエラー
  • → 全体が catch に飛んでしまう
  • 成功したデータも無視される

✅ 良い例:Promise.allSettled(成功・失敗を個別に扱う)

// 良い例:すべての結果を「成功/失敗」ごとに安全に処理
async function loadAllDataSafe() {
  const urls = [
    'https://jsonplaceholder.typicode.com/posts/1',
    'https://jsonplaceholder.typicode.com/posts/9999999', // ← 失敗する
    'https://jsonplaceholder.typicode.com/posts/3'
  ];

  const results = await Promise.allSettled(
    urls.map(url => fetch(url))
  );

  for (const result of results) {
    if (result.status === 'fulfilled') {
      const res = result.value;
      if (res.ok) {
        const data = await res.json();
        console.log('✅ 成功:', data.title);
      } else {
        console.warn('⚠️ HTTPエラー:', res.status);
      }
    } else {
      console.error('❌ ネットワークエラー:', result.reason);
    }
  }

  console.log('すべてのfetchが完了しました(失敗も含めて)');
}

loadAllDataSafe();
JavaScript

🔍 結果

✅ 成功: sunt aut facere repellat provident occaecati...
⚠️ HTTPエラー: 404
✅ 成功: ea molestias quasi exercitationem repellat qui ipsa sit aut
すべてのfetchが完了しました(失敗も含めて)

解説まとめ

比較項目悪い例(Promise.all)良い例(Promise.allSettled)
処理の性質1つでも失敗すると全体失敗成功・失敗を個別に報告
部分成功できないできる
使う場面すべて成功しないと意味がない処理一部だけでも使いたい処理(例:画像、記事、コメント)

さらに改善:finallyで「後処理」を加える

async function loadAllDataWithCleanup() {
  const urls = [
    'https://jsonplaceholder.typicode.com/posts/1',
    'https://jsonplaceholder.typicode.com/posts/9999999',
    'https://jsonplaceholder.typicode.com/posts/3'
  ];

  try {
    const results = await Promise.allSettled(urls.map(url => fetch(url)));

    const validData = [];
    for (const result of results) {
      if (result.status === 'fulfilled' && result.value.ok) {
        validData.push(await result.value.json());
      }
    }
    console.log('取得成功データ:', validData);
  } catch (e) {
    console.error('予期しないエラー:', e);
  } finally {
    console.log('✅ 全リクエスト終了(後処理実行)');
  }
}

loadAllDataWithCleanup();
JavaScript

まとめ

  • Promise.all → 全部成功しないと catch に落ちる
  • Promise.allSettled → 成功と失敗を「全部報告」してくれる
  • finally → 成否に関係なく「後処理」を実行できる

タイトルとURLをコピーしました