🙆

【JavaScript入門】Promiseの基本

に公開

処理の流れ

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Promise より画像引用

Promise(プロミス)

「将来的に必ず何らかの結果(成功または失敗)になることが約束されている値」を表すオブジェクトのことを指します。

Promise を生成するには、コンストラクタ( new Promise() )を使用し、その中にエグゼキュータ関数(Executor Function)と呼ばれる関数を渡すのが基本です。

エグゼキュータ関数は、JavaScriptによって引数として自動的に2つのコールバック関数を受け取ります。

  1. resolve
    非同期処理が成功したときに呼び出す関数

  2. reject
    非同期処理が失敗したときに呼び出す関数

Promiseコンストラクタ内で非同期処理を定義し、その結果に応じて resolve または reject を呼び出すことで、非同期処理の状態を管理し、後続の .then() や .catch() へとその状態を伝えることができます。

Promise の3つの状態

Pending(保留)

処理がまだ進行中

Fulfilled(成功)

  • 処理が成功して完了した状態
  • resolve() が呼び出された後の状態

Rejected(失敗)

  • 処理が失敗して完了した状態
  • reject() が呼び出された後の状態

※「Fulfilled」または「Rejected」のどちらかの状態になったことを総称して 「Settled」(確定済み)と呼びます。

Promise の受け取り方(使い方)

1. コールバック形式: .then() と .catch()

非同期処理が完了するのを待って、その結果(成功または失敗)に応じて処理を記述する方法です。

askQuestion('名前は?')
  .then((result) => {
    // 成功したとき(resolveが呼ばれたとき)に実行される
    console.log(`入力された名前: ${result}`);
  })
  .catch((error) => {
    // 失敗したとき(rejectが呼ばれたとき)に実行される
    console.error(`エラーが発生しました: ${error}`);
  });

// Promiseは非同期なので、then() の中の処理を待たずに以下の行が先に実行される
console.log('質問はしたけど、回答を待たずに次の行の処理は進むよ'); 

2. 同期形式: async/await

Promise を返す関数の結果を、あたかも同期処理のように(順番に)待ちながら受け取る方法です。

async function main() { // awaitを使う関数は async をつける
  try {
    // askQuestion が完了して結果(answer)が返ってくるまで、ここで処理を停止(待機)する
    const name = await askQuestion('名前は?');
    console.log(`入力された名前: ${name}`);

    const age = await askQuestion('年齢は?');
    console.log(`入力された年齢: ${age}`);

  } catch (error) {
    console.error(`エラーが発生しました: ${error}`);
  }
}

main(); // async 関数を実行する

Promise の生成と利用の基本的な流れ

1. Promise の作成(生成)

非同期処理(rl.question など)を Promise コンストラクタでラップし、結果が出たときに resolve または reject を呼び出します。

// askQuestion の中身
return new Promise((resolve) => {
    // 非同期処理を開始
    rl.question('質問文', (answer) => {
        // 非同期処理が成功したとき
        resolve(answer); 
    });
    // 失敗の可能性がないため reject は省略
});

resolve() は、非同期処理が完了し、成功裏に結果が得られたときに、そのコールバック関数の内部で呼び出されます。

resolve() の役割は値を運ぶことであり、その値を使って何をするかは Promise の外側で記述します。

2. Promise の利用

値を使って何をするか
async function run() {
    // resolve(answer) で運ばれてきた値が foodAnswer に代入されるまで待機する
    const foodAnswer = await askQuestion('好きな食べ物は?'); 
    
    // 成功したい処理、つまり値を利用したい処理をここに記述する
    console.log(`${foodAnswer} がお好きなんですね!`); 
}

resolve() の2つの役割

  1. 状態の変更
    resolve() が呼び出されると、その Promise オブジェクトの状態が Pending(保留中) から Fulfilled(成功/完了) へと変化します。この状態変化は元に戻せません。

  2. 結果の伝達
    resolve(value) のように引数として渡された valueを、その Promise を待っている側のコード(.then() のコールバックや await の左辺の変数)に結果として引き渡します。

まとめ

  • Promise は将来結果を受け取ることが約束されたオブジェクト
  • Promise は状態を管理している(Pending, Fulfilled, Rejected)
関数 役割 Promiseの状態変化
resolve(value) 非同期処理の成功を通知し、結果の値を渡す Pending → Fulfilled (成功)
reject(reason) 非同期処理の失敗を通知し、エラー情報を渡す Pending → Rejected (失敗)

参考URL

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Promise

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/async_function

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/await

Discussion