【javascript】Promiseについて学ぶ①

Promiseについてまとめます。


# Promiseとは
非同期処理をわりかしすっきり書くことができる書き方。
`わりかし`と書いたのは、`コールバックを駆使して書くよりもすっきり書くことができる`という意味です。

# Promiseの基本
Promiseを使うときの基本手順です。

####1．Promiseコンストラクタに非同期に処理したいことを書いたコールバックを引数として渡し、オブジェクト化する
newしてオブジェクト化することができます。
コールバック関数には、引数にresolve、rejectを渡す必要があります。

####2．成功時はresolve、失敗時はrejectを呼ぶ
非同期処理では、処理が成功したときはresolve、失敗したときはrejectを呼び出します。

####3．Promiseオブジェクトをリターンする
####4．成功時、失敗時に関数を実行したいのならば、then()メソッドを使う
Promiseオブジェクトに対してthen()を使用することで、成功時、失敗時に実行したい関数を登録することができます。


以下、サンプルコードを用いて詳しく説明します。


```sample.js

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 以下のようにも書けます

```sample-then.js
1  asyncFunc().then(function (data) {
2      console.log(data);  // onFulfilled
3  }, function (err) {
4      console.log(err);  // onRejected
5  });
```

####L14~22 catchを使って以下のようにも書けます

```sample-catch.js
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()だと動きが異なります。

```sample-then.js
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は実行されません。

```sample-catch.js
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()についてまとめようと思います。