書いて覚えるPromise

# Promiseとは？
Promiseは非同期処理の完了or失敗を表すオブジェクト。

- 非同期処理の成功（resolve）、失敗（reject）を表すオブジェクト
- `then`や`catch`, `finally`メソッドを使うことで非同期処理後に関数を実行することができる
- `Promise.all`や`Promise.race`を使えば、非同期処理を並列で実行することができる

# Promiseを使った処理を書いてみよう

## resolve（成功）の例
- 非同期処理が成功した場合は、`resolve(結果の値)` を呼ぶ
- 非同期処理成功後に行いたい処理は、`then()`メソッドに関数を渡すことで実現できる

```javascript
new Promise((resolve, reject) => {
  setTimeout(() => {
    // 成功する例なので、resolveを返す
    resolve('非同期処理 成功!!');
  }, 3000);
}).then((value) => {
  console.log('=== thenメソッド内 ===');
  console.log('resolveされた値: ' + value);
}).catch((value) => {
  console.log('=== catchメソッド内 ===');
  console.log('rejectされた値: ' + value);
});
```

- 実行結果

```
$ node promise.js
=== thenメソッド内 ===
resolveされた値: 非同期処理 成功!!
```

## reject(失敗)の例
- 非同期処理が失敗した場合は、`reject(Errorオブジェクト)`を呼ぶ
- 非同期処理失敗時に実行したい処理は、`catch()`メソッドに関数を渡すことで実現できる

```javascript
new Promise((resolve, reject) => {
  setTimeout(() => {
    // 失敗する例なので、rejectを返す
    reject(new Error('非同期処理 失敗.....'));
  }, 3000);
}).then((value) => {
  console.log('=== thenメソッド内 ===');
  console.log('resolveされた値: ' + value);
}).catch((value) => {
  console.log('=== catchメソッド内 ===');
  console.log('rejectされた値: ' + value);
});
```

- 実行結果

```
=== catchメソッド内 ===
rejectされた値: Error: 非同期処理 失敗.....
```

## finally 成功しても、失敗しても実行する処理の例
成功しても、失敗しても実行したい処理は、`finally()`に関数を渡すことで実現できる。

```javascript

new Promise((resolve, reject) => {
  setTimeout(() => {
    reject(new Error('非同期処理 失敗.....'));
  }, 3000);
}).then((value) => {
  console.log('=== thenメソッド内 ===');
  console.log('resolveされた値: ' + value);
}).catch((value) => {
  console.log('=== catchメソッド内 ===');
  console.log('rejectされた値: ' + value);
}).finally(() => {
  console.log('=== finallyメソッド内 ===');
  console.log('DONE!!')
});
```

- 実行結果

```
=== catchメソッド内 ===
rejectされた値: Error: 非同期処理 失敗.....
=== finallyメソッド内 ===
DONE!!
```

## 非同期処理の並列実行の例

### Promise.all
- `Promise.all()`にPromiseオブジェクトの配列を渡す
- 全てresolve(成功)した時に、`then()`が実行される
- どれか１つでもreject(失敗)した時は、`catch()` が実行される

例えば、２つのAPIを叩いて、2つとも成功したときに何か処理をするみたいなことをしたい場合は、

```javascript

const postAPI1 = new Promise((resolve, reject) => {
  console.log('API1を叩く');
  setTimeout(() => {
    resolve('API1成功');
  }, 3000);
})

const postAPI2 = new Promise((resolve, reject) => {
  console.log('API2を叩く');
  setTimeout(() => {
    resolve('API2成功');
  }, 200);
})

Promise.all([postAPI1, postAPI2]).then((values) => {
  console.log('=== thenメソッド内 ===')
  console.log(values);
});
```

- 実行結果

```
API1を叩く
API2を叩く
=== thenメソッド内 ===
[ 'API1成功', 'API2成功' ]
```

### Promise.race
- `Promise.race()`にPromiseオブジェクトの配列を渡す
- 1つでもresolve(成功), reject（失敗）が呼び出されたら、`then`もしくは`catch`が実行される
- `then`や`catch`メソッドには最初に完了した処理の値が渡される

```javascript
const postAPI1 = new Promise((resolve, reject) => {
  console.log('API1を叩く');
  setTimeout(() => {
    reject(new Error('API1失敗'));
  }, 3000);
})

const postAPI2 = new Promise((resolve, reject) => {
  console.log('API2を叩く');
  setTimeout(() => {
    resolve('API2成功');
  }, 200);
})

// postAPI2の方がsetTimeoutを短めに設定しているので、先に処理が完了する。
// そのためthenの処理が実行される。
Promise.race([postAPI1, postAPI2])
  .then((value) => {
    console.log('=== thenメソッド内 ===');
    console.log(value);
  }).catch((value) => {
    console.log('=== catchメソッド内 ===');
    console.log(value);
  });
```

- 実行結果

```
API1を叩く
API2を叩く
=== thenメソッド内 ===
API2成功
```

# 参考
- http://azu.github.io/promises-book/