Promiseの使い方
コールバック関数は、ネスト(入れ子)にすることができますが、複雑になります。このような時は、Promiseを使うと便利です。
本ページでは、Promiseについて説明します。
コールバック関数のネスト
関数を順番に呼び出したい時、コールバック関数をネストできます。

以下は、例です。
function func1(callback) {
alert("func1完了");
callback();
}
function func2(callback) {
alert("func2完了");
callback();
}
function func3() {
alert("func3完了");
}
func1(function() {
func2(function() {
func1(function() {
func2(func3);
});
});
});
上記はfunc1→func2→func1→func2→func3の順番で呼び出されますが、赤字の所がわかり辛いと思います。これに引数や変数などが加わってくると、記述していても間違いやすくなります。
このようにコールバック関数は、簡単に次の関数を指定できるメリットがありますが、ネストするとわかり辛いデメリットがあります。
Promiseで書き換えた場合
先ほどの例をPromiseを使って書き換えると、以下になります。
function func1() {
alert("func1完了");
}
function func2() {
alert("func2完了");
}
function func3() {
alert("func3完了");
}
Promise.resolve()
.then(func1)
.then(func2)
.then(func1)
.then(func2)
.then(func3);
赤字が書き換えた部分ですが、実行される順番が非常にわかり易くなったと思います。
thenは、処理が完了するたびに呼び出される関数を指定します。
Promiseチェーン
Promiseでは、returnで返す値をthenで呼ばれる関数に渡せます。以下は、例です。
function func1(x){ alert(x); return "2番目"; } function func2(x){ alert(x); } Promise.resolve("1番目") .then(func1) .then(func2);
return "2番目"によって、func2には文字列"2番目"が渡されます。これにより、上記は「1番目」の次に「2番目」がアラートとして表示されます。
このように、値を次の関数に渡したりして処理が連結されることをPromiseチェーンと呼びます。
Promiseの状態
Promiseは、以下の3つの状態を持ちます。
- pending(保留)
- 処理中
- fulfilled(満足)
- 処理が成功
- rejected(拒否)
- 処理が失敗
Promiseチェーンで示した例で言えば、func1を呼び出した時点がpendingです。func1が終了した時点がfulfilledで、次のthenで指定した処理が始まり、再度pendingになります。
エグゼキューター関数
Promiseは、成功と失敗で処理を分けて記述できます。
function func1(resolve, reject){ let x = Math.ceil( Math.random() * 2); if(x == 1){ resolve("成功"); } else { reject("失敗"); } } function func2(z){ alert(z); } const promise1 = new Promise(func1); promise1 .then(func2) .catch(func2);
func1は、エグゼキューター関数と呼ばれます。resolve()によって、Promiseの状態がfulfilledになり、thenで指定した関数が呼び出されます。reject()では、Promiseの状態がrejectedになり、catchで指定した関数が呼び出されます。
このため、上記はxが1の時は「成功」とアラート表示され、それ以外では「失敗」とアラート表示されます。
非同期処理との組み合わせ
Promiseは、resolveかrejectが返るまで、次の処理に移りません。このため、非同期処理が終わるまで待つことができます。以下は、非同期処理のsetTimeoutと組み合わせて使う例です。
function func1(resolve, reject){ setTimeout(function(){resolve("処理完了");}, 5000); } function func2(x){ alert(x); } const promise1 = new Promise(func1); promise1 .then(func2);
上記は、プロミスの成功時だけを扱っています。func1が実行され、setTimeoutでは5秒待つことになります。5秒後にresolve();が実行されますが、これが成功を示します。成功を示す応答があると、次のthenでfunc2が処理されます。つまり、5秒後にfunc2が実行されて、「処理完了」のアラートが表示されます。
もし、Promiseを使わずにfunc1とfunc2を実行すると、5秒待たずにアラートが表示されます。また、func1の中でsetTimeoutの次にalert("処理完了");と記述しても、5秒待たずにアラートが表示されます。これは、setTimeoutの中の処理は5秒待ちますが、その下の処理は非同期で進むためです。
関連ページ
- JavaScript基礎「非同期処理」
- 非同期処理として、setTimeout、setInterval、async functionやawaitなどの使い方、setTimeout、setIntervalのキャンセル方法を説明しています。