Promiseについてなんかいい感じに書くその２

**またしても間に合わなかったどころか次の日のポストより遅かった・・・すみません**

----
この記事ですが、前編の記事を読んでいて、ある程度理解していることが前提となります。
もし良かったら前編の記事もお読みください。

前回 => [promiseについてなんかいい感じに書く](https://qiita.com/wh1tecat/items/d78a59b42ec61ffd765c)

----
さて、前編ではpromiseについて話し、~~糞みたいな~~コールバック地獄がキレイスッキリ！になりましたね。
後編ではpromiseの便利な機能と、更に便利に使う方法について書いていきます。

# allとrace
まずは便利な機能の話からしましょう。
既に前編の説明で十分便利だったPromiseですが、確かに連続した処理をするときには便利ですが、同時に実行したい！　という時はちょっと不便です。

ひとつサンプルを出してみます。
前回はあるAPIから取得したデータで次のAPIを叩いて...といった例でしたが、今回は複数のAPIを同時に叩いてその結果をまとめる処理・・・ですが、これを実現するのは既に難しいです。
とりあえず無理やりコードにしてみます。

```javascript
let data1, data2, data3;

getFromAPI(request1)
.then((data) => {data1 = data;})
.catch((error) => {console.error(error)});
getFromOtherAPI(request2)
.then((data) => {data2 = data;});
.catch((error) => {console.error(error)});
getFromSomeOtherAPI(request3)
.then((data) => {data3 = data;});
.catch((error) => {console.error(error)});

const check = setInterval(() => {
  if (data1 !== undefined && data2 !== undefined && data3 !== undefined) {
    viewRendering(data1, data2, data3);
    clearInterval(check);
  }
}, 100);
```

やりようは色々あるでしょうが、こんな感じでしょうか。。。もう誰が見てもわかる酷さですね。

さて、こんな例を出したからにはもちろんこれからする説明はこれを解決するものです。
まずは`Promise.all()`

これは引数にpromiseの配列を与えることで、
> 配列内のpromiseを同時に実行し、全てが完了するか、一つでも失敗した場合、thenまたはcatchに移る

メソッドです。

先程のサンプルを直してみましょう。

```javascript
Promise.all([getFromAPI(request), getFromOtherAPI(request), getFromSomeOtherAPI(request)])
.then((result) => {viewRendering(result[0], result[1], result[2])})
.catch((error) => {console.error(error)});
```
たった三行に収まりました！

では次はPromiseのもう一つのメソッド`Promise.race`です。

こちらは引数は同じくpromiseの配列を与えるのですが、処理に関しては違い
> 与えたpromiseを同時に実行し、一番最初に返ってきた完了または失敗をthen,catchに渡す

メソッドになります。

こちらは上で上げたサンプルでは使えないので、別の例を考えてみます。
実用的な例だと・・・複数のAPIを同時に叩き、一番最初に返ってきた結果を返す　とかでしょうか。
同じ結果を返すAPIのうち一番速度が早かったものを使用する例なんかも考えられますね。
サンプルコードを・・・と思いましたが殆どallと変わりませんでした・・・
一応乗せておきます。

```javascript
Promise.race([getFromAPI(request), getFromOtherAPI(request), getFromSomeOtherAPI(request)])
.then((result) => {viewRendering(result)})
.catch((error) => {console.error(error)});
```

といったところでPromiseの便利なメソッドは終わりです。

はい。終わりです。 Promise自体にはメソッドはこれしかありません。

では便利な機能はこれで終わりか、いえいえ違います。

# async/await

ここまでPromiseについて色々書いてきた上、タイトルも`Promiseについてなんかいい感じに書く`ですが、いよいよ本題です。　

実はここまでは全て前座です。

## async
javascriptの関数定義時に`async`をつけて関数を定義すると、結果をpromiseにして返す関数にすることができます。
コードにしてみましょう。

```javascript
async function testFucntion1() {
  return "test1";
}

const testFunction2 = async () => {
  return "test2";
}

const testFunction3 = async () => {
  throw new Error("error");
}

testFunction1()
.then((result) => {console.log(result)}); // true

testFunction2()
.then((result) => {console.log(result)}); // true

testFunction3()
.catch((err) => {console.error(err)}); // Error: err
```

といった感じです。
いちいちpromiseを書かなくても勝手にPromise関数にしてくれる。
確かに便利ですが、asyncは基本的にawaitとセットで使います。

## await
さらっと概要を説明すると、async関数内でpromiseを返す関数を呼び出す時にawaitをつけるとその関数が同期的に実行されるようになります。

こっちは恐らく言葉だとちょっと解りづらいと思うので、コードベースで説明します。

```javascript
(async () => {
  const data = await getFromAPI(request);
  console.log(data);
})()
```
全体のサンプルコードとしてはこんな感じです。
では一行ずつ説明します。

```javascript
(async () => {
...
}())
```
awaitはasync関数外では使えず、エラーになってしまうので、ここでは即時実行関数を作ってasync関数にしています。

```javascript
const data = await getFromAPI(request);
```
これまでのpromiseでは`.then`, `.catch`で結果を受け取っていましたが、awaitで同期化した関数では、通常の関数と同じように結果を受け取ることができます。

```javascript
console.log(data);
```
同期化していて、`getFromAPI`内の処理が終わった段階で次の処理に移るため、promiseの際と違って普通に次の行で呼び出しても問題ありません。

Promise, async/awaitをうまく使うことで、もうコールバック地獄に悩まされることはないでしょう。

#　あとがき
とまぁ、今回はそもそも書きはじめすら投稿予定日に間に合わないという前回以上のポカをやらかしてますが、書きたかったPromiseについてはおおよそまとめられたので良しとします。

それでは、12/10(２日も過ぎたけど)の`Make IT Advent Calendar 2018`、お役に立ちましたでしょうか？

ここまでご愛読頂き、ありがとうございました！