Skip to content

8.3 Promiseを使う

Promise は、ES2015で追加された非同期処理を扱うための機能です。非同期処理を行う関数はコールバック関数を直接受け取るのではなく、Promise オブジェクトを返すようになり、非同期処理をより抽象的・統一的に扱うことができます。

Node.jsの fs/promises モジュールを用いると、Promiseベースの非同期APIを利用できます。

  • Promiseの取得: readFile("foo.txt", "utf8") のように呼び出すと、処理結果を待たずに即座に Promise オブジェクト(Promise<string> 型など)が返されます。この時点で既に非同期処理は裏で開始されています。
  • thenメソッド: 返された Promise オブジェクトの then メソッドにコールバック関数を渡すと、非同期処理が成功(解決)した際に、その結果を引数として関数が呼び出されます。

8.3.2 コールバック関数の登録とエラー処理(1)

Section titled “8.3.2 コールバック関数の登録とエラー処理(1)”

Promise は処理の「成功」と「失敗」の2つの結果を持ちます。

  • catch メソッド: 処理が失敗(reject)した場合に呼び出されるコールバック関数を登録します。
  • エラーの型: 失敗時に渡されるエラー情報の型はTypeScript上ではデフォルトで any になるため、(error: unknown) => { ... } のように安全な型注釈をつけることが推奨されます。

8.3.3 コールバック関数の登録とエラー処理(2)

Section titled “8.3.3 コールバック関数の登録とエラー処理(2)”
  • finally メソッド: 成功・失敗のどちらの場合でも必ず呼び出されるコールバック関数を登録します。このコールバック関数は引数を受け取りません。

8.3.4 自分でPromiseオブジェクトを作る

Section titled “8.3.4 自分でPromiseオブジェクトを作る”

既存のコールバック関数ベースの非同期処理を、自作の Promise に変換することができます。

  • 構文: new Promise<T>((resolve, reject) => { ... })
  • 解決と拒否: 引数の executor 関数の中で非同期処理を行い、成功時には resolve(結果) を、失敗時には reject(エラー) を呼び出すことで、作られたPromiseオブジェクトの状態を確定させます。
  • Promise.resolve(値): 与えられた値を結果として、即座に成功するPromiseオブジェクトを作ります。
  • Promise.reject(値): 即座に失敗するPromiseオブジェクトを作ります。 (※即座に解決されたPromiseであっても、登録された then のコールバックは同期的な処理が全て終わった後、非同期的に実行されます。)

複数のPromiseを組み合わせて新しいPromiseを作るメソッドです。

  • Promise.all: 渡されたPromiseの配列が「すべて成功」したら成功となり、それぞれの結果をまとめた配列を返します(1つでも失敗すると即座に全体が失敗します)。複数の非同期処理を並行して実行する際に非常に頻繁に使われます。
  • Promise.race: 最も早く成功、または失敗したPromiseの結果を全体の結果とします。タイムアウト処理の実装などに有効です。
  • Promise.allSettled: 成功・失敗に関わらず、すべてのPromiseの結果が出るまで待ちます。結果は各Promiseの成否ステータス(fulfilledrejected)を含んだオブジェクトの配列となります。
  • Promise.any: どれか1つでも成功した時点で成功となります。すべて失敗した場合にのみエラー(AggregateError)となります。

8.3.8 Promiseチェーン (1) チェーンを作る

Section titled “8.3.8 Promiseチェーン (1) チェーンを作る”

thencatch メソッドは、呼び出されると「新しいPromiseオブジェクト」を作って返します。

  • 値の変換: then のコールバック関数で値を return すると、それが新しく作られたPromiseの成功結果となります。
  • 失敗のリカバリー: catch のコールバック関数で値を返すと、元のPromiseの失敗を「成功」に変換して次のチェーンへ渡すことができます。
  • これらを p.then(...).catch(...) のように繋げて書く記法を Promiseチェーン と呼びます。

8.3.9 Promiseチェーン (2) 非同期処理の連鎖

Section titled “8.3.9 Promiseチェーン (2) 非同期処理の連鎖”

then のコールバック関数で「別のPromiseオブジェクト」を返り値として返した場合、ネストは発生せず、返されたPromiseの結果が出るまでチェーン全体の解決が遅延します。これにより、非同期処理を順番に(直列に)連鎖させることができます。

8.3.10 Promiseチェーン (3) エラーの扱い

Section titled “8.3.10 Promiseチェーン (3) エラーの扱い”
  • エラーの発生: then の中で throw を使って例外を発生させると、返されるPromiseは「失敗」となります。
  • Unhandled Promise Rejection: 失敗したPromiseに対して catch 等でエラーハンドリングがされていないと、プロセスが強制終了してしまう致命的なエラーになります。
  • 安全なチェーン: p.then(...).catch(...) のようにチェーンの末端で確実にエラーをキャッチし、ハンドリング漏れを防ぐ設計が重要です。

import("モジュール名") という構文で、モジュールを実行時に非同期で読み込むことができます。

  • 結果: モジュールの名前空間オブジェクトを結果とする Promise が返されます。
  • 用途: そのモジュールが必要になるまで読み込みを遅延させたい(遅延読み込み・コード分割)場合に重宝します。