IT・WEB・ゲーム業界の転職に強いR-Stone

転職コラム

Javascriptのpromiseとは?基本的な書き方や注意点をご紹介

JavaScriptの非同期処理の要、Promiseを詳しく解説します。Promiseとは何か、なぜ必要なのか、どう使用するのか。基本的な概念から実践的な使用方法まで、順を追って説明します。

resolveとrejectの役割、thenメソッドの活用法、エラー処理の重要性など、Promiseを使いこなすために必要な知識を網羅。さらに、async/await構文との関連性にも触れます。

本記事を通じて、Promiseの理解を深め、より効率的なコーディングを実現しましょう。

Promiseとは?

PromiseはJavaScriptで非同期処理の結果を扱うためのオブジェクトです。

非同期処理とは、ある処理の完了を待たずに次の処理を実行できる仕組みのことを指します。

Promiseは非同期処理の3種の状態(fulfilled、rejected、pending)を追跡して、非同期処理を適切に管理できるので、複雑な非同期処理を整理でき、エラー処理も統一的におこなえるため、コードの可読性と保守性が向上します。

非同期処理とコールバックの意味

非同期処理は、時間のかかる操作(例:データ取得)を実行中も他の処理を続行できる手法で、アプリケーションの応答性が向上し、ユーザー体験が改善されます。

また、コールバックは非同期処理の結果を受け取る関数です。しかし、複数の非同期処理を連続しておこなう場合、コールバックの入れ子(「コールバック地獄」)が発生するケースもあります。

Promiseを使用すると、複雑なコールバックの連鎖を回避し、より管理しやすいコードを記述できます。

promiseの基本的な書き方

新しいPromiseオブジェクトを作成するには、new Promise()コンストラクタを使用します。

コンストラクタは、resolverejectの引数2つを持つ関数を受け取ります。

const myPromise = new Promise(function(resolve, reject) {

  // ここに非同期処理を記述

});

アロー関数を使うと、コールバックをより簡潔に記述できます。

const myPromise = new Promise((resolve, reject) => {

  // ここに非同期処理を記述

});

resolveの使い方

resolveは、Promise(の非同期処理)が成功したときに呼び出す関数です。非同期処理が正常に完了したら、resolveを呼び出して結果を渡します。

const successPromise = new Promise((resolve, reject) => {

  setTimeout(() =>// 1秒かかる処理の例

    resolve(‘成功しました’); // 成功時のデータを渡す

  }, 1000);

});

resolveに渡された値は、後続のthenメソッドで受け取ることができます。

rejectの使い方

rejectは、Promiseが失敗したときに呼び出す関数です。エラーが発生した場合や処理が失敗した場合に使用します。

const failPromise = new Promise((resolve, reject) => {

  setTimeout(() => {

    reject(new Error(‘エラーが発生しました’)); // エラーオブジェクトを渡す

  }, 1000);

});

rejectに渡されたエラーは、catchメソッドで捕捉できます。

thenの使い方

thenメソッドは、Promiseが成功(fulfilled)したときに実行される処理を定義します。

Promiseは3つの状態(fulfilled、rejected、pending)があり、非同期処理の結果に応じて状態が変化します。

thenは2つの引数を取ります。1つ目は成功時、2つ目は失敗時のコールバック関数です。

myPromise.then(

  (result) => console.log(result), // 成功時の処理

  (error) => console.error(error)  // 失敗時の処理(省略可)

);

複数のthenをチェーンすれば、非同期処理を順序立てて実行できます。

コールバックの使い方

Promiseのコールバック関数は、非同期処理の結果を受け取って処理をおこなうために使用します。

myPromise

  .then(result => {

    console.log(result); // 成功時の処理

    return result * 2;   // 次のthenに渡す値

  })

  .then(doubledResult => {

    console.log(doubledResult); // 前のthenの結果を使用

  })

  .catch(error => {

    console.error(error); // エラー処理

  });

promiseを使用する際の注意点

Promiseを使用する際の重要な注意点を見ていきましょう。

catchメソッドでエラーを処理する

Promiseチェーンでのエラー処理は重要です。

適切に処理されないエラーは静かに無視される可能性があるため、catchメソッドを使用した確実なエラー捕捉と処理が推奨されます。

somePromise()

  .then(result => {

    // 成功時の処理

  })

  .catch(error => {

    console.error(‘エラーが発生しました:’, error);

    // ここでerrorに応じたエラー処理をおこなう

  });

finallyメソッドでクリーンアップする

finallyメソッドは、Promiseの成功・失敗に関わらず実行される処理を定義できます。finallyは、リソースのクリーンアップなどに有用です。

somePromise()

  .then(result => {

    // 成功時の処理

  })

  .catch(error => {

    // エラー処理

  })

  .finally(() => {

    // 必ず実行される処理(接続を閉じる、画面を切り替えるなど)

  });

Promiseの並行処理(.all/.race)

複数のPromiseを扱う場合、並行処理を制御するメソッドを活用してください。

Promise.allはすべてのPromiseが解決されるまで待ち、Promise.raceは最初に解決されたPromiseの結果を返します。

Promise.all([promise1, promise2, promise3])

  .then(results => {

    // すべてのPromiseが解決されたあとの処理。resultsは結果の配列

  });

 

Promise.race([promise1, promise2, promise3])

  .then(result => {

    // 最初に解決されたPromiseの結果(他のPromiseは実行を続ける)

  });

async/await構文

async/awaitはPromiseをもとにした見やすい構文で、より同期的な書き方でPromiseを扱えます。

awaitはasyncの付いた関数内でのみ記述でき、awaitに与えたPromiseが終了するまで待ちます。

async function fetchRandomDogImage() {  // 関数の前にasyncキーワードを付ける

  try { // async/awaitではtry-catch文を使用してエラーを処理できる

    const response = await fetch(‘https://dog.ceo/api/breeds/image/random’);

    if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);

 

    const data = await response.json();

    if (data.status === “success”) {

      console.log(‘犬の画像URL:’, data.message);

    }

  } catch (error) { // エラー処理

    console.error(‘エラーが発生しました:’, error.message);

  }

} // async関数は常にPromiseを返す

fetchRandomDogImage();  // 関数を呼び出す

まとめ

Promiseを使うことで、コールバック地獄を回避し、読みやすい非同期処理を実現できます。

また、Promiseとあわせてasync/await構文も使いこなすと、より効果的な非同期プログラミングが可能になります。

基本的な書き方や注意点を押さえ、実際のコーディングで活用してみましょう。