【ITニュース解説】Promise in JavaScript
2025年09月10日に「Dev.to」が公開したITニュース「Promise in JavaScript」について初心者にもわかりやすく解説しています。
ITニュース概要
JavaScriptのPromiseは、非同期処理の「成功」または「失敗」と結果を表すオブジェクトだ。状態はPending(処理中)、Fulfilled(成功)、Rejected(失敗)の3つ。成功時に.then()、失敗時に.catch()で処理を記述し、非同期処理を管理するのに役立つ。
ITニュース解説
JavaScriptにおけるPromiseは、非同期処理、すなわちサーバーからのデータ取得やファイルの読み込みといった時間のかかる処理が、将来的に成功したか失敗したか、そしてその結果がどのような値であったかを表すためのオブジェクトである。ウェブアプリケーションでは、ユーザーインターフェースの応答性を保ちながら裏で重い処理を進めることが重要であり、Promiseはそのような非同期処理を管理する上で中心的な役割を果たす。
Promiseは、その非同期処理の進行状況に応じて三つの状態を持つ。一つ目は「Pending(保留中)」である。これは処理がまだ進行中であり、結果がまだ確定していない初期状態を示す。二つ目は「Fulfilled(成功)」である。これは非同期処理が無事に完了し、成功したことを意味する。Promiseの内部でresolveと呼ばれる関数が呼び出されることでこの状態に移行し、成功した結果の値が確定する。三つ目は「Rejected(失敗)」である。これは非同期処理が何らかの問題によって失敗したことを意味する。rejectと呼ばれる関数が呼び出されることでこの状態に移行し、失敗の原因となるエラー情報が確定する。一度FulfilledまたはRejectedの状態になると、そのPromiseの状態は確定し、二度と変化することはない。
Promiseを新たに作成するには、new Promise()という構文を使用する。この際、Promiseのコンストラクタには、非同期処理の具体的な内容を記述する関数を引数として渡す。この関数は二つの引数、resolveとrejectを受け取る。非同期処理が成功した場合は、結果の値を引数としてresolve()関数を呼び出す。一方、処理が失敗した場合は、エラー情報を引数としてreject()関数を呼び出す。例えば、簡単なタスクの成功・失敗をシミュレートする際、タスクが成功したと判断できればresolve("タスク完了!")のように呼び出し、失敗した場合はreject("タスク失敗!")のように呼び出すことで、そのPromiseの状態と結果を決定できる。
作成されたPromiseの最終的な結果を受け取るには、.then()メソッドと.catch()メソッドを使用する。.then()メソッドは、PromiseがFulfilled(成功)状態になったときに実行される処理を登録するために使われる。このメソッドに渡す関数は、Promiseがresolveされたときに渡された成功結果の値を受け取る。例えば、promise.then(result => console.log("成功:", result))のように記述すると、成功時のメッセージと結果をコンソールに出力できる。一方、.catch()メソッドは、PromiseがRejected(失敗)状態になったときに実行される処理を登録するために使われる。.catch()に渡す関数は、Promiseがrejectされたときに渡されたエラー情報を受け取る。promise.catch(error => console.log("エラー:", error))のように記述することで、失敗時のエラーメッセージを処理できる。これらのメソッドはチェーン形式で連続して記述できるため、非同期処理の成功と失敗のハンドリングを簡潔かつ読みやすく記述することが可能となる。
より実践的な例として、データ取得をシミュレートする関数を考える。getDataという関数がPromiseを返すように設計し、その内部でsetTimeout関数を用いて、例えば2秒間の遅延を発生させることで、ネットワーク通信のような時間のかかる非同期処理を模倣できる。2秒後、データが正常に取得できたと仮定してresolve("データ受信!")を呼び出すか、取得に失敗したと仮定してreject("データ取得失敗。")を呼び出す。このgetData関数を呼び出し、その結果として返されるPromiseに対して.then()と.catch()を適用することで、2秒後に成功または失敗のメッセージを受け取り、その後の処理を分岐させることが可能となる。
Promiseには、.then()や.catch()以外にも便利なメソッドがいくつか存在する。.finally()メソッドは、Promiseが成功したか失敗したかにかかわらず、最終的に必ず実行される処理を登録するために使用される。例えば、データ取得中に表示していたローディングアニメーションを、取得の成否にかかわらず非表示にするような後処理に最適である。Promise.all()メソッドは、複数のPromiseを配列で受け取り、それら全てのPromiseが成功するまで待機する。全てのPromiseが成功した場合、それぞれのPromiseの成功した結果が配列として返される。もし配列内のPromiseのうち一つでも失敗すると、Promise.all()全体がその失敗したPromiseのエラーとともにRejected状態となる。これは、複数の異なるデータを同時に取得し、全て揃ってから次の処理に進めたい場合に非常に有効である。Promise.race()メソッドも複数のPromiseを配列で受け取るが、こちらは最も早く完了したPromiseの結果のみを返す。ここでいう「完了」とは、成功(Fulfilled)または失敗(Rejected)のどちらでもよく、一番早く状態が確定したPromiseのその結果(成功値またはエラー)がPromise.race()全体の結果となる。これは、複数のデータソースから同じ種類のデータを取得し、最も早く応答があったものだけを採用したい場合などに利用できる。
このようにPromiseは、JavaScriptにおける非同期処理をより効率的かつ安全に扱うための強力な仕組みである。非同期処理の完了を待機し、その成功と失敗を明確に区別し、さらに複数の非同期処理を連携させるための統一された方法を提供することで、複雑になりがちな非同期処理のコードを読みやすく、保守しやすくする。