Promiseは、非同期処理の状態と結果を表現するオブジェクトです。この状態は3種類。
状態 | 概要 |
---|---|
pending | 処理が実行中 |
fulfilled | 処理が正常に完了した |
rejected | 処理が失敗した |
また、Promise
オブジェクトは then
catch
finally
の3つのメソッドをもち、いずれもまたPromise
オブジェクトを返します。これらのメソッドが呼ばれるのは、
メソッド | 呼ばれるとき |
---|---|
then | Promiseの処理が成功 = fulfilled |
catch | Promiseの処理が失敗 = rejected |
finally | Promiseの完了または失敗 |
のタイミングです。なんとなく try - catch - finally
の構文に似ていますね。
then
, catch
はそれぞれ成功/失敗した場合に呼び出されるコールバック関数を引数にとり、then
のコールバック関数の引数にPromiseの結果、catch
のコールバック関数の引数にはPromiseが失敗した理由(Errorが入ることが多い)が渡されます。
// const promise = Promiseオブジェクト; これ以降のコードでは省略
promise.then(result => {
// resultにはPromiseの返り値が代入される
}).catch(reason => {
// reasonにはPromiseが失敗した理由(Errorほか)が代入される
}).finally(() => {
// 引数をとらない。fulfilledでもrejectedでも呼び出される
});
Promiseオブジェクトの作り方は主に、
-
fetch
などの関数の返り値 -
async function
キーワードを用いた非同期関数 -
Promise
コンストラクタnew Promise((resolve, reject) => { ... })
があります。基本的には1つ目のように使うことが多く、直接的にPromiseオブジェクトを生成することは少ないと思います。
Promise
コンストラクタは引数に関数を取り、その引数 resolve
に値を渡すことでPromiseはfulfilledになり、reject
に値を渡す、もしくはErrorをthrow
することでPromiseはrejectedになるという仕組みです。
new Promise((resolve, reject) => {
︙
resolve(引数);
}).then(result => {
// resultにはresolveの引数が入っている
});
new Promise((resolve, reject) => {
︙
reject(引数);
// もしくは
throw Errorオブジェクト;
}).catch(reason => {
// reasonはrejectの引数かthrowされたオブジェクトが入っている
});
then, catch のもう少し細かな仕様
then
メソッドはもうひとつコールバック関数をとることができます。この2つ目のコールバック関数はPromiseが失敗したときに呼び出されます。つまり、catch
の内容をthen
に書くことができます。実際に、catch
メソッドは内部的にthen
メソッドを呼び出すとされています。
promise.then(result => { ... }).catch(reason => { ... });
// 上下でやっていることは同じ
promise.then(result => { ... }, reason => { ... });
余談: Promiseはつづくよどこまでも
先述した通り、
Promise
オブジェクトはthen
catch
finally
の3つのメソッドをもち、いずれもまたPromise
オブジェクトを返します
ので、
promise
.then(result => { ... })
.then(result => { ... })
.then(result => { ... })
.then(result => { ... })
.then(result => { ... })
.then(result => { ... })
.then(result => { ... })
︙
と無限につなげることができます。2連続程度はfetch
などで利用例がありますが、ここまで多くつなげる必要もないような...。