4. Promise

Promiseの基本概念と使い方を学びます。Promiseの仕組み、then/catchメソッドの使い方、Promiseチェーンとエラーハンドリングを実践的に学習します。

この章で学べること

  • Promiseとは何かを理解する
  • Promiseの3つの状態(pending, fulfilled, rejected)を学ぶ
  • then、catch、finallyメソッドの使い方を習得する
  • メソッドチェーンを使った効率的なコードの書き方を学ぶ
  • 実践的な演習を通じてPromiseを習得する

Promiseとは?

Promise は「非同期処理の結果を表すオブジェクト」です。

ピザを注文する例で説明します。ピザを注文したらすぐにピザが届くわけではありませんが、配達員は後で届けると約束します。多くの場合は熱々のピザが届けられますが、配達員が誤ってピザを落としてしまう可能性もゼロではありません。結果は「ピザが届く」か「何か問題が起きた」かのどちらかです。

このように結果は後で出る結果は成功か失敗のどちらか、というのがPromiseの特徴です。

Promiseの状態について

Promiseは以下の3つの状態のどれかを持ちます。

pending

待機中

初期状態。まだ成功も失敗もしていない。結果を待っている状態

fulfilled

成功

処理が成功して完了した状態

rejected

失敗

処理が失敗した状態

Promiseの基本構文

Promiseは new Promise で作成することができます。その際に、 resolvereject の2つの関数を引数として受け取ります。処理が成功した場合は、resolveを実行し、処理が失敗した場合はrejectを実行します。

以下はPromiseの基本的なサンプルコードです。

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

  if (success) {
    resolve('ピザの配達に成功しました!');
  } else {
    reject('ピザの配達が失敗しました。');
  }
});

解説

上記のコードでは、successがtrueのため、resolveが実行され、Promiseの状態は成功(fulfilled)になります。

Promiseの基本的な使い方

thenメソッドで成功時の処理を記述

Promiseが成功(fulfilled)した時に実行される処理は、thenメソッドで記述します。

myPromise.then((result) => {
  console.log("結果:", result);
  console.log("ピザパーティを始めましょう!")
});

catchメソッドでエラー処理

Promiseが失敗(rejected)した時に実行される処理は、catchメソッドで記述します。

myPromise.catch((error) => {
  console.log("結果:", error);
  console.log("残念ですね。返金してもらいましょう。")
});

finallyメソッド

finallyメソッドは、成功・失敗に関係なく、必ず実行される処理を定義します。必要ない場合は省略することができます。

// 成功しても失敗しても実行したい処理を書く
myPromise.finally(() => {
  console.log("片付けをして帰りましょう!");
});

完全な例

以下が完全なサンプルコードです。ピザの配達が成功した場合と失敗した場合の処理を実装しています。

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

  if (success) {
    resolve('ピザの配達に成功しました!');
  } else {
    reject('ピザの配達が失敗しました。');
  }
});

// 成功時の処理
myPromise.then((result) => {
  console.log("結果:", result);
  console.log("ピザパーティを始めましょう!")
});

// 失敗時の処理
myPromise.catch((error) => {
  console.log("結果:", error);
  console.log("残念ですね。返金してもらいましょう。")
});

// 成功しても失敗しても実行したい処理を書く
myPromise.finally(() => {
  console.log("片付けをして帰りましょう!");
});

実行結果

結果: ピザの配達に成功しました! ピザパーティを始めましょう! 片付けをして帰りましょう!

メソッドチェーン

Promiseのthenメソッド、catchメソッド、finallyメソッドは続けて書くことができます。これにより、より読みやすく効率的なコードを書くことができます。先ほどのコードをメソッドチェーンで記述したものが以下です。

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

  if (success) {
    resolve('ピザの配達に成功しました!');
  } else {
    reject('ピザの配達が失敗しました。');
  }
});

// メソッドチェーンで記述
myPromise
  .then((result) => {
    console.log("結果:", result);
    console.log("ピザパーティを始めましょう!")
  })
  .catch((error) => {
    console.log("結果:", error);
    console.log("残念ですね。返金してもらいましょう。")
  })
  .finally(() => {
    console.log("帰る前に片付けをしましょう!");
  });

Promiseの注意点

Promiseを使う際に注意すべき重要なポイントがあります。

非同期処理のタイミング

Promiseは非同期で実行されるため、処理の完了を待たずに次のコードが実行されます。以下の例を見てみましょう。

let result;
fetchData().then(r => result = r);
console.log(result); // ←まだundefined

注意

上記のコードでは、console.log(result)undefinedを出力します。これは、fetchData()の処理が完了する前にconsole.logが実行されるためです。

正しい書き方

Promiseの結果を正しく取得するには、thenメソッド内で処理を行う必要があります。

// 正しい書き方
fetchData().then(result => {
  console.log(result); // 正しく結果が表示される
  // ここでresultを使った処理を行う
});

ポイント

  • Promiseの結果はthenメソッド内でのみ利用可能
  • 非同期処理の完了を待ってから次の処理を実行したい場合は、メソッドチェーンを使用
  • 複数の非同期処理を順番に実行したい場合は、thenを連続して使用

実践演習

演習①:Promiseの状態を理解しよう

以下のコードを実行したときのPromiseの状態を予想してください。

// コード1: 初期状態
const promise1 = new Promise((resolve, reject) => {
  // 何も実行しない
});

// コード2: 成功状態
const promise2 = new Promise((resolve, reject) => {
  resolve("成功しました");
});

// コード3: 失敗状態
const promise3 = new Promise((resolve, reject) => {
  reject("エラーが発生しました");
});

各Promiseの状態を選択してください

promise1の状態
promise2の状態
promise3の状態

演習②:Promiseの処理順序を理解しよう

以下のコードを実行したときの出力順序を予想してください。

const promise = new Promise((resolve, reject) => {
  console.log("A");
  resolve("B");
});

console.log("C");

promise.then(result => console.log(result));

console.log("D");

出力順序を選択してください

演習③:非同期処理のタイミングを理解しよう

以下のコードを実行したときのresultの値を予想してください。

let result;
fetchData().then(r => result = r);
console.log(result);

resultの値を選択してください

演習④:基本的なPromise作成

以下の要件を満たすPromiseを作成してください。

  • 1秒後にランダムで成功または失敗する
  • 成功時は「データを取得しました」を表示
  • 失敗時は「データの取得に失敗しました」を表示
// ヒント:1秒後にランダムで成功または失敗するコード
setTimeout(() => {
  // Math.random()は0以上1未満のランダムな数値を返します
  const randomValue = Math.random();
  
  if (randomValue > 0.5) {
    // 0.5より大きい場合は成功
  } else {
    // 0.5以下の場合は失敗
  }
}, 1000);

実践してみよう

上記のコードを実際に書いて実行してみましょう。コードエディタで練習できます。

コードエディタで練習する

まとめ

Promiseは、非同期処理を扱うための強力なツールです。以下のポイントを理解しましょう。

  1. Promiseの3つの状態: pending(待機中)、fulfilled(成功)、rejected(失敗)
  2. メソッドチェーン: then、catch、finallyを組み合わせて使用
  3. エラーハンドリング: catchメソッドでエラーを適切に処理
  4. 非同期処理の制御: 処理の完了を待ち、結果に応じた処理を実行

Promiseを理解することで、非同期処理をより効率的に扱えるようになります。次のステップとして、async/awaitについて学びます。

次回予告

次回はNode.jsのasync/awaitについて学びます。