【初心者向け】JavaScriptでPromiseを使いこなす!catchとthenの基礎から応用まで

2024-06-17

JavaScript、Node.js、Promiseにおける catch と then の配置

JavaScript、Node.jsにおける非同期処理において、Promiseは重要な役割を果たします。Promiseには、処理完了時に実行されるthenメソッドと、処理失敗時に実行されるcatchメソッドが用意されています。

本記事では、catchメソッドとthenメソッドの配置について、分かりやすく解説します。

catchメソッドとthenメソッドの配置には、2つのパターンがあります。

thenメソッドの前に配置

promise
  .catch(error => {
    console.error('エラーが発生しました:', error);
  })
  .then(result => {
    console.log('処理が完了しました:', result);
  });

この場合、Promiseが拒否された場合のみ、catchメソッド内の処理が実行されます。Promiseが完了した場合は、catchメソッドはスキップされ、thenメソッド内の処理が実行されます。

promise
  .then(result => {
    console.log('処理が完了しました:', result);
  })
  .catch(error => {
    console.error('エラーが発生しました:', error);
  });

この場合、Promiseが完了した場合もthenメソッド内の処理が実行され、その後、Promiseが拒否された場合のみ、catchメソッド内の処理が実行されます。

どちらの配置が適切か?

  • エラー処理を独立させたい場合: catchメソッドをthenメソッドの前に配置します。

補足

  • catchメソッドは、Promiseチェーンのどこでも配置できます。
  • 複数のcatchメソッドを連続して配置することもできます。
  • Promiseが拒否された場合、その後のthenメソッドはスキップされます。

以下のコードは、非同期処理を2回実行し、いずれかの処理が失敗した場合にエラー処理を行う例です。

const promise1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    if (Math.random() < 0.5) {
      resolve('処理1が完了しました');
    } else {
      reject(new Error('処理1が失敗しました'));
    }
  }, 1000);
});

const promise2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    if (Math.random() < 0.5) {
      resolve('処理2が完了しました');
    } else {
      reject(new Error('処理2が失敗しました'));
    }
  }, 2000);
});

promise1
  .then(result => {
    console.log(result);
    return promise2;
  })
  .catch(error => {
    console.error('処理1が失敗しました:', error);
    return promise2; // 処理2を継続実行
  })
  .then(result => {
    console.log(result);
  })
  .catch(error => {
    console.error('処理2が失敗しました:', error);
  });

catchメソッドとthenメソッドの配置は、状況に応じて適切な方法を選択することが重要です。本記事を参考に、Promiseを効果的に活用してください。




    catchメソッドをthenメソッドの前に配置

    const promise = new Promise((resolve, reject) => {
      setTimeout(() => {
        if (Math.random() < 0.5) {
          resolve('成功しました');
        } else {
          reject(new Error('失敗しました'));
        }
      }, 1000);
    });
    
    promise
      .catch(error => {
        console.error('エラーが発生しました:', error);
      })
      .then(result => {
        console.log('処理が完了しました:', result);
      });
    

    このコードでは、50%の確率でPromiseが拒否されます。catchメソッドがthenメソッドの前に配置されているため、Promiseが拒否された場合は、catchメソッド内の処理が実行され、thenメソッドはスキップされます。

    const promise = new Promise((resolve, reject) => {
      setTimeout(() => {
        if (Math.random() < 0.5) {
          resolve('成功しました');
        } else {
          reject(new Error('失敗しました'));
        }
      }, 1000);
    });
    
    promise
      .then(result => {
        console.log('処理が完了しました:', result);
      })
      .catch(error => {
        console.error('エラーが発生しました:', error);
      });
    

    複数のcatchメソッドを配置

    const promise = new Promise((resolve, reject) => {
      setTimeout(() => {
        if (Math.random() < 0.3) {
          resolve('成功しました');
        } else if (Math.random() < 0.6) {
          reject(new Error('エラー1が発生しました'));
        } else {
          reject(new Error('エラー2が発生しました'));
        }
      }, 1000);
    });
    
    promise
      .catch(error => {
        console.error('エラーが発生しました:', error.message); // エラーメッセージを取得
      })
      .catch(error => {
        if (error.message === 'エラー1が発生しました') {
          console.error('エラー1を補足しました');
        }
      })
      .then(result => {
        console.log('処理が完了しました:', result);
      });
    

    このコードでは、30%の確率でPromiseが成功し、30%の確率でエラー1が発生しました、40%の確率でエラー2が発生しましたとなります。

    最初のcatchメソッドは、すべてのエラーを補足します。2番目のcatchメソッドは、error.messageを使用してエラーの種類を判別し、エラー1が発生しましたのみを補足します。

    これらのサンプルコードは、catchメソッドとthenメソッドの配置と、複数のcatchメソッドの使用方法を理解するのに役立ちます。状況に応じて適切な方法を選択してください。




    その他のcatchとthenの配置方法

    非同期エラー処理

    非同期処理において、エラーが発生した箇所と別の箇所でエラー処理を行う場合があります。

    この場合、以下の様にthencatchを組み合わせることができます。

    const asyncFunction = async () => {
      try {
        const result = await someAsyncOperation();
        console.log(result);
      } catch (error) {
        console.error('エラーが発生しました:', error);
        // エラー処理を行う
      }
    };
    
    asyncFunction();
    

    このコードでは、someAsyncOperationが非同期処理を実行します。someAsyncOperationが成功した場合、then内の処理が実行されます。一方、someAsyncOperationが失敗した場合、catch内の処理が実行されます。

    エラーハンドリングとデフォルト値の設定

    Promiseが拒否された場合、デフォルト値を設定したい場合があります。

    const promise = new Promise((resolve, reject) => {
      setTimeout(() => {
        if (Math.random() < 0.5) {
          resolve('成功しました');
        } else {
          reject(new Error('失敗しました'));
        }
      }, 1000);
    });
    
    promise
      .then(result => {
        console.log('処理が完了しました:', result);
      })
      .catch(error => {
        console.error('エラーが発生しました:', error);
        console.log('デフォルト値:', defaultValue); // デフォルト値を設定
      });
    

    このコードでは、50%の確率でPromiseが拒否されます。catch内の処理では、エラーメッセージを出力した後、defaultValueという変数にデフォルト値を設定します。

    複数のPromiseを処理し、それぞれ異なる処理を実行したい場合があります。

    const promise1 = new Promise((resolve, reject) => {
      setTimeout(() => {
        if (Math.random() < 0.5) {
          resolve('処理1が完了しました');
        } else {
          reject(new Error('処理1が失敗しました'));
        }
      }, 1000);
    });
    
    const promise2 = new Promise((resolve, reject) => {
      setTimeout(() => {
        if (Math.random() < 0.5) {
          resolve('処理2が完了しました');
        } else {
          reject(new Error('処理2が失敗しました'));
        }
      }, 2000);
    });
    
    promise1
      .then(result => {
        console.log(result);
        return promise2;
      })
      .catch(error => {
        console.error('処理1が失敗しました:', error);
        return promise2; // 処理2を継続実行
      })
      .then(result => {
        console.log(result);
      })
      .catch(error => {
        console.error('処理2が失敗しました:', error);
      });
    

    このコードでは、2つのPromiseを連続して実行します。いずれかのPromiseが拒否された場合、catch内の処理が実行されますが、その後、残りのPromiseが継続実行されます。

    これらの方法は、catchthenを柔軟に組み合わせるための例です。状況に応じて適切な方法を選択してください。


    javascript node.js promise


    URL 解析の便利なツール 3 選! JavaScript でできること

    URL を解析するには、いくつかの方法があります。最も一般的な方法は、URL オブジェクトと location オブジェクトを使用する方法です。URL オブジェクトは、URL を表すために使用されます。このオブジェクトには、ホスト名、パス、クエリ文字列、ハッシュフラグメントなどのプロパティがあります。URL を解析するには、以下の手順を行います。...


    【徹底比較】テキスト入力フィールドのカーソル位置取得:JavaScript、jQuery、HTMLそれぞれのメリットと特徴

    概要本記事では、JavaScript、jQuery、HTMLを用いて、テキスト入力フィールド内のカーソル位置(文字数)を取得する方法を解説します。それぞれの方法における利点と注意点も詳しく説明しますので、目的に合った方法を選択してください。...


    Node.jsでBase64エンコード:3つの方法を徹底比較!

    方法1:Bufferクラスを使用するNode. jsのBufferクラスは、バイナリデータを扱うためのクラスです。 このクラスを使用して、文字列やバイナリデータをBase64エンコードすることができます。方法2:cryptoモジュールを使用する...


    TypeScript で ES6 Map を使いこなす

    Map の利点:キーと値のペアを保存するのに最適な方法です。他のデータ構造 (オブジェクトなど) よりも高速で効率的です。さまざまな種類のデータ (オブジェクト、配列、文字列など) を保存できます。繰り返し処理や検索が簡単です。TypeScript で Map を使用するには、Map 型を使用します。...


    Node.js、TypeScript、グローバルスコープ拡張:エラー「Augmentations for the global scope can only be directly nested in external modules or ambient module declarations(2669)」の解決策

    このエラーは、TypeScriptでNode. jsのグローバルスコープ拡張を試みた際に発生します。これは、グローバルスコープ拡張は外部モジュールまたはambientモジュール宣言内でのみ直接ネストできるという制限によるものです。原因TypeScriptでは、グローバルスコープは特別なモジュールとして扱われます。そのため、他のモジュールと同様に拡張するには、いくつかの規則に従う必要があります。...