10.1 Promiseとは
Promise は、非同期処理の「結果(成功または失敗)」を管理するための特別なオブジェクトです。
一言で言うと「非同期処理の結果を約束する仕組み」です。
例えば、前章の最初で、サーバーから大量のデータを取得するなど、すぐに結果が出ない処理に対して、Promise は「成功したか」「失敗したか」を後から通知してくれます
この荷物の配達に例えられる3つの状態を、以下の言葉で表します。
Pending(待機中)
非同期処理が完了しておらず、処理が完了するのを待っています。いわば、荷物が配達中の状態。
Fulfilled(成功)
非同期処理が終わった後で、処理が正常に終了した状態。配達に成功し、荷物も無事に届いている。
Rejected(失敗)
非同期処理が終わった後で、処理が異常終了した状態(エラー)。配達に失敗し、荷物が届いてない。

10.1.1 Promise オブジェクトを作るプログラム
Promise オブジェクトを作成する際は、コンストラクタ引数として「実行したい処理」を記述した関数を渡します。この関数には、JavaScript から自動的に 2 つの引数 resolve と reject が渡されます。これらは、処理の結果を通知するための 「スイッチ(ボタン)」 だと考えてください。
まずは、ランダムな数値によって成功(resolve)と失敗(reject)が変わるシンプルな例を見てみましょう。
ソースフォルダ:public/ch10
ファイル名:promise-basic.js
➢ promise-basic.html
前の章で作った ch09/callback-hell.html をコピーし、ch10 にペーストしてください。
その際に、ファイル名を promise-basic.html に変更します。
ファイル内の callback-hell.html や callback-hell.js の記述も、promise-basic.html や promise-basic.js に修正します。
➢ promise-basic.js
// promise-basic.js
// 1. Promise(約束)の作成
const myPromise = new Promise((resolve, reject) => {
// 成功か失敗かをランダムに決める
const isSuccess = Math.random() > 0.5;
if (isSuccess) {
// 成功通知
resolve("成功しました!");
} else {
// 失敗通知
reject("失敗しました…(エラー発生)");
}
});
// 2. 結果の受け取り
myPromise
.then((message) => {
// resolveされた場合に動き、アラートを出す
alert(`【結果】${message}`);
})
.catch((errorMessage) => {
// rejectされた場合に動き、エラーログを出す
alert(`【結果】${errorMessage}`);
})
.finally(() => {
// 最後に必ず実行する
alert("処理が完了しました。");
});
実行結果

解説
このプログラムは 2 つのセクションで成り立ってます。
前半の 4 行目から 15 行目では、myPromise という名前で新しい Promise オブジェクトを生成しています。
ここでは仮に 6 行目の Math.random()で生成させた乱数が 0.5 より大きいか小さいかを元に、Promise の結果が resolve(処理成功)か reject(処理失敗)かを決めるようにしています。
6: const isSuccess = Math.random() > 0.5;
乱数の結果が 0.5 より大きい場合:resolve(処理成功)として”成功しました!”の値を返す。
10: resolve("成功しました!");
乱数の結果が 0.5 より小さい場合:reject(処理失敗)として”失敗しました…(エラー発生)”の値を返す。
13: reject("失敗しました…(エラー発生)");
この前半部で判定された結果を元に、後半の 18 行目から 26 行目で処理を分岐します。
Promise オブジェクトは、前半部の結果判定が終わった後で resolve と reject の結果に対応して自動的に呼び出される、以下の 3 つのメソッドを持っています。

18 行目で、myPromise を呼び出した後、まるで数珠つなぎの様に.then() と.catch() が並んでいます。
それぞれのアロー関数の先にあるのが、resolve だった時に動くメソッドの処理の中身と、reject だった時に動くメソッドの処理の中身です。
myPromise の状態が確定すると、結果に該当するメソッドだけが実行され、最後に必ず.finally が実行されます。このような.(ドット)で改行してメソッドを書くスタイルをメソッドチェーンと言います。
また、わざわざ結果が reject だった場合のメソッドを .catch() で定義しているのには意味があります。
実務での非同期処理(通信など)では、必ず結果が成功するとは限りません。「サーバーがダウンしている」「通信が切れた」といったトラブルが起きた際、プログラムをフリーズさせずに「エラーが起きた」ことを正しく通知するために reject が存在します。
これにより、.catch() から始まるメソッドの中で、安全にエラー対応(アラートを出すなど)を行うことができます。
10.1.2 Promise とメソッドチェーンでコールバック地獄を解消するプログラム
Promise を使うと、前章で学んだ「コールバック地獄」をどのように改善できるか確認しましょう。
複数の処理をメソッドチェーンにすることで、コードのネスト(入れ子)を深くせずに記述することができます。
ソースフォルダ:public/ch10
ファイル名:delay2.js
➢ delay2.html
前の項で作った ch10/promise-basic.html をコピーし、ch10 にペーストしてください。
その際に、ファイル名を delay2.html に変更します。ファイル内の promise-basic.html や promise-basic.js の記述も、delay2.html や delay2.js に修正します。
➢ delay2.js
// delay2.js
// 指定した秒数待機する関数「delay」を定義します
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
// 1秒ごとにメッセージを出します
delay(1000)
.then(() => {
alert("1秒経過:ステップ1完了");
return delay(1000); // 次のステップのためのPromiseを返す
})
.then(() => {
alert("さらに1秒経過:ステップ2完了");
});
実行結果

解説
今回のサンプルでは、4~6 行目で定義されている delay という function がポイントになります。
戻り値として、新たな Promise オブジェクトを生成し、その先で呼び出した setTimeout 関数の引数として ms で与えられた時間が経過したら、コールバック関数として resolve を実行させています。
これによって、Promise オブジェクトは、指定時間経過後に .then() を常に実行するようになります。
4: function delay(ms) {
5: return new Promise(resolve => setTimeout(resolve, ms));
6: }
仮に、これを省略せずに書くと、このようになります。
4: return new Promise(resolve => {
5: setTimeout(() => {
6: // 指定した時間(ms)が経過したら、ここで resolve() を実行する
7: resolve();
8: }, ms);
9: });
コールバック関数の記述が簡単になるのが、アロー関数の良いところでもありますが、このような場合には、逆に関数なのかわかりづらくなりますので、慣れないうちは注意しましょう。
