Promiseについてまとめます。
Promiseとは
非同期処理をわりかしすっきり書くことができる書き方。
わりかし
と書いたのは、コールバックを駆使して書くよりもすっきり書くことができる
という意味です。
Promiseの基本
Promiseを使うときの基本手順です。
####1.Promiseコンストラクタに非同期に処理したいことを書いたコールバックを引数として渡し、オブジェクト化する
newしてオブジェクト化することができます。
コールバック関数には、引数にresolve、rejectを渡す必要があります。
####2.成功時はresolve、失敗時はrejectを呼ぶ
非同期処理では、処理が成功したときはresolve、失敗したときはrejectを呼び出します。
####3.Promiseオブジェクトをリターンする
####4.成功時、失敗時に関数を実行したいのならば、then()メソッドを使う
Promiseオブジェクトに対してthen()を使用することで、成功時、失敗時に実行したい関数を登録することができます。
以下、サンプルコードを用いて詳しく説明します。
1 function asyncFunc() {
2 return new Promise(function (resolve, reject) { // 手順1、3
3 // ここ以下に非同期に処理したい内容を書きます
4 async(function(err, data){ // 仮想の関数です。
5 if (err) {
6 reject(err); // 手順2 失敗したのでrejectを呼び出す
7
8 }
9 resolve(data); // 手順3 成功したのでresolveを呼び出す
10 });
11 });
12 }
13
14 function onFulfilled(data) {
15 console.log(data);
16 }
17
18 function onRejected(err) {
19 console.log(err);
20 }
21
22 asyncFunc().then(onFulfilled, onRejected); // 手順4
23
####L2: return new Promise(function (resolve, reject) {・・・
new Promise(callback)
でPromiseオブジェクトを作ることができます。
callbackには非同期に処理したいことを書きます。
また、このcallbackでは引数にresolveとrejectを渡す必要があります。
newでオブジェクトを作り、returnすることで、asyncFunc関数を実行したとき(L22)にPromiseオブジェクトを返すようにします。
####L6: reject(err);
ここでは仮想のasync関数を使用しています。
errがあった場合、処理は失敗とします。そのときに、rejectを呼び出します。
####L9: resolve(data);
errがなかった場合、処理は成功とします。そのときにresolveを呼び出します。
####L22: asyncFunc().then(onFulfilled, onRejected);
then関数を使用することによって、成功時、失敗時に実行する関数を登録することができます。
asyncFunc関数の戻り値はPromiseオブジェクトですので、then()はインスタンスメソッドです。
成功時にはonFulfilledが実行され、失敗時にはonRejectedが実行されます。
ここでいう、成功時、失敗時というのはそれぞれ、非同期処理中にresolve、rejectが呼ばれた時のことです。
####L14~22 以下のようにも書けます
1 asyncFunc().then(function (data) {
2 console.log(data); // onFulfilled
3 }, function (err) {
4 console.log(err); // onRejected
5 });
####L14~22 catchを使って以下のようにも書けます
1 asyncFunc().then(function(data) {
2 console.log(data);
3 }).catch(function(err) {
4 console.log(err);
5 });
.catch()
については、.then(undefined, onRejected)
と同じ意味になります。
Promiseオブジェクトの状態
インスタンス化したPromiseのオブジェクトには3つの状態があります。
- Fulfilled
- 成功したとき。すなわちresolveされたとき。このときonFulfilledが呼ばれる
- Rejected
- 失敗したとき。すなわちrejectされたとき。このときonRejectedが呼ばれる
- Pending
- FulfilledでもRejectedでもないとき。初期状態等が含まれる。
非同期処理の中で成功と判断したときにresolve()を呼び出す→Fulfilledの状態になる
非同期処理の中で失敗と判断したときにreject()を呼び出す→Rejectedの状態になる
ということのようですね。
resolveされたときはthen()の第1引数に渡された関数が実行されます。
rejectされたときはthen()の第2引数に渡された関数、もしくはcatch()に渡した関数が実行されます。
thenとcatch
rejectされたときの関数の実行について、then()とcatch()だと動きが異なります。
1 asyncFunc().then(function (data) {
2 console.log('onFulfilled' + data); // onFulfilled
3 }, function (err) {
4 console.log('onRejected' + err); // onRejected
5 });
上記のsample-then.jsの場合、asyncFunc関数でRejected状態になったときにL4が実行されます。
また、asyncFunc関数でFulfilled状態になったときは、L2が実行されます。このL2が実行されているときにエラーが起きた場合(このコードだと発生しませんが・・・)には、L4は実行されません。
1 asyncFunc().then(function(data) {
2 console.log('onFulfilled' + data);
3 }).catch(function(err) {
4 console.log('onRejected' + err);
5 });
上記のsample-catch.jsの場合、asyncFunc関数でRejected状態になったときにはsample-then.jsと同様、L4が実行されます。
また、asyncFunc関数でFulfilled状態になったときも同様に、L2が実行されています。
ですが、L2が実行中にエラーが起こった場合もL4が実行されます。この点がthenを使ったときと違う動きとなります。
上記のようなそれぞれの動きに違いを考えて、使用する必要があります。
今回はここまでとします。
次はall()についてまとめようと思います。