JavaScriptでプロミスチェーンを用いたエラーハンドリングのベストプラクティス

JavaScriptでプロミスチェーンを用いたエラーハンドリングのベストプラクティス

プロミスチェーンはJavaScriptで非同期処理を扱う際の重要なツールです。正しくエラーハンドリングを行うことで、コードの信頼性を向上させることができます。本記事では、プロミスチェーンを使用した効果的なエラーハンドリング方法を解説します。

プロミスチェーンの基本構造

プロミスチェーンを用いて一連の非同期操作を順番に実行します。

fetch('https://api.example.com/data')
  .then(response => response.json())
  .then(data => {
    console.log(data);
  })
  .catch(error => {
    console.error('Error:', error);
  });

個別のthenでエラーハンドリング

各ステップで独立したエラーハンドリングを行います。

fetch('https://api.example.com/data')
  .then(response => {
    if (!response.ok) {
      throw new Error('Network response was not ok');
    }
    return response.json();
  })
  .then(data => console.log(data))
  .catch(error => console.error('Fetch error:', error));

catchの配置場所の重要性

catchを適切な位置に配置することで、全体のエラーをキャッチします。

fetch('https://api.example.com/data')
  .then(response => response.json())
  .then(data => {
    console.log(data);
    throw new Error('Test error');
  })
  .catch(error => console.error('Caught in catch:', error));

最終的な処理を行うfinally

エラーハンドリングに関わらず必ず実行されるfinallyを活用します。

fetch('https://api.example.com/data')
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error('Error:', error))
  .finally(() => console.log('Operation complete'));

複数のプロミスのエラーハンドリング

Promise.allを使用した場合のエラーハンドリングです。

Promise.all([
  fetch('https://api.example.com/data1'),
  fetch('https://api.example.com/data2')
])
  .then(responses => Promise.all(responses.map(response => response.json())))
  .then(data => console.log(data))
  .catch(error => console.error('Error in Promise.all:', error));

個別のプロミスのエラー処理

個々のプロミスでエラーが発生した場合に対応します。

Promise.allSettled([
  fetch('https://api.example.com/data1'),
  fetch('https://api.example.com/data2')
])
  .then(results => {
    results.forEach(result => {
      if (result.status === 'fulfilled') {
        console.log('Success:', result.value);
      } else {
        console.error('Error:', result.reason);
      }
    });
  });

非同期関数との組み合わせ

async/awaitとプロミスチェーンを組み合わせたエラーハンドリングです。

async function fetchData() {
  try {
    const response = await fetch('https://api.example.com/data');
    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.error('Error:', error);
  } finally {
    console.log('Operation complete');
  }
}

fetchData();

再スローによるエラー伝播

catch内でエラーを再スローして処理を継続します。

fetch('https://api.example.com/data')
  .then(response => response.json())
  .catch(error => {
    console.error('Temporary Error:', error);
    throw error; // エラーを再スロー
  })
  .then(data => console.log(data))
  .catch(error => console.error('Final Error:', error));

カスタムエラーハンドリング関数の活用

エラーハンドリングを関数化して再利用性を向上させます。

function handleError(error) {
  console.error('Error occurred:', error.message);
}

fetch('https://api.example.com/data')
  .then(response => response.json())
  .catch(handleError);

ログとアラートの組み合わせ

エラーをログに記録し、ユーザーに通知します。

fetch('https://api.example.com/data')
  .then(response => response.json())
  .catch(error => {
    console.error('Error:', error);
    alert('An error occurred. Please try again later.');
  });

ネストされたプロミスのエラーハンドリング

ネストされたプロミスチェーンにおけるエラーハンドリングです。

fetch('https://api.example.com/data')
  .then(response => response.json())
  .then(data => {
    return fetch(`https://api.example.com/details/${data.id}`)
      .then(detailsResponse => detailsResponse.json());
  })
  .then(details => console.log(details))
  .catch(error => console.error('Error in nested chain:', error));

エラーハンドリングのベストプラクティス

適切なエラーハンドリングの戦略を選択するためのヒントです。

  • catchはプロミスチェーンの終端に配置する
  • finallyでリソースを解放する
  • Promise.allSettledを利用して部分的な成功を処理する
  • エラーの詳細をユーザーに分かりやすく伝える

まとめ

プロミスチェーンは強力なツールですが、エラーハンドリングが適切でないとコードが脆弱になります。ベストプラクティスを取り入れて、信頼性の高い非同期コードを実現しましょう。