非同期処理 async、await[JavaScript]


非同期なJavaScripについてまとめ、Promiseについてもまとめたので、
最後にasync、awaitについてまとめていこうと思います。

async、awaitは、Promiseをより簡単に書くことのできる糖衣構文になります。


>※糖衣構文(とういこうぶん)とは？ wiki 参照：
>
>プログラミング言語において、読み書きのしやすさのために導入される書き方であり、複雑でわかりにくい書き方と全く同じ意味になるものを、よりシンプルでわかりやすい書き方で書くことができるもののことである。

非同期処理の考え方やPromiseについては、下記で記載させていただいてます。ご参考までに。

https://qiita.com/shisshi_engineer/items/6cfbd29820ac8607ae5b

https://qiita.com/shisshi_engineer/items/ed9832bc1257ca42c15b

## 目次：

- [async関数](#async関数)
- [await演算子](#await演算子)
- [Promiseがresolveされた時の値の使用](#promiseがresolveされた時の値の使用)
- [Promiseがrejectされた時の値の使用](#promiseがrejectされた時の値の使用)

## async関数

・async関数は必ずPromiseを返す
・関数が値を返せば、Promiseはその値でresolveを返す
・関数がエラーをthrowした場合、Promiseはそのエラーでrejectする

asyncはfunctionの前に記載することにより、その関数がasync functionであることを宣言します。「アロー関数でも使用することができます。」
こうすることで、この関数はasyncな関数（非同期）と定義することができます。

async宣言をした関数は、自動的にPromiseを返すようになります。

#### async function resolveの例

```js
const sing = async() => {
    return 'ドレミファドラシド';
}

sing().then((data) => {
    console.log('成功!!:', data)
});
```

async functionがあって、そこからreturnされたものに関しては、
Promiseのresolveに渡ってくることを確認できます。

```text:出力結果：
成功: ドレミファソラシド
```

#### async function rejectの例

・エラーをthrowする

```js
const sing = async() => {
    throw new Error('問題が起きました！！');
    return 'ドレミファドラシド';
}

sing().then((data) => {
    console.log('成功!!:', data)
})
.catch((err) => {
    console.log('エラー')
    console.log(err);
});
```
returnの前にerrをthrowするように設定したので、
エラーのログが出力されているのを確認できます。

```text:出力結果：
エラー
app.js:34 Error: 問題が起きました！！
at sing (app.js:25:11)
at app.js:29:1
```

## await演算子

awaitはasync関数の中でしか使えない
awaitはPromiseがresolveまたはrejectするまでasync関数の実行を一時的に止める

#### async、awaitを使った例

1秒ごとにHTMLの背景色が赤、オレンジ、黄色、緑、青と5回変わる関数delayedColorChangeをPromiseを使って作成してみました。


こちらの関数をasync awaitを使って作成する場合、どのように変更できるかやってみたいと思います。

```js
const delayedColorChange = (color, delay) => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            document.body.style.backgroundColor = color;
            resolve();
        }, delay)
    })
}

delayedColorChange('red', 1000)
    .then(() => delayedColorChange('orange',1000))
    .then(() => delayedColorChange('yellow',1000))
    .then(() => delayedColorChange('green',1000)) 
    .then(() => delayedColorChange('blue',1000))
```
async awaitを使ってみる

```js
async function rainbow() {
    await delayedColorChange('red',1000);
    await delayedColorChange('orange',1000);
    await delayedColorChange('yellow',1000);
    await delayedColorChange('green',1000);
    await delayedColorChange('blue',1000);
}

rainbow();
```

async関数にして　await することにより、delayedColorChangeのPromiseがresolveあるいは、rejectするのを待ってくれるようになります。

なので、awaitしたタイミングで、Promiseがresolveを待ち受けて、受け取ることによりdelayedColorChangeの色の変更が順番に行われます。

これにより、Promiseで作成した時よりもさらに直感的に作成することが可能となります。

## Promiseがresolveされた時の値の使用

以前使っていたfakeRequest関数を使い、
async awaitでPromiseがresolveされた時の値の使用方法をみていこうと思います。

```js
const fakeRequest = (url) => {
    return new Promise((resolve, reject) => {
        const delay = Math.floor(Math.random() *(4500)) + 500;
        setTimeout(() => {
            if(delay > 4000) {
                reject('コネクションタイムアウト')
            } else {
                resolve(`ダミーデータ(${url})`)
            }
        }, delay)
    })
}
```

関数の説明：
1. Promiseを作成します。
2. ランダムな時間待ちます。0.5秒-５秒
3-1. ランダムな時間が4秒より多くかかる場合は、rejectします。
3-2. そうでない場合は、resolveします。
*** 

fakeRequestを実行するasyncな関数を定義します。

```js
async function makeRequest() {
    const data1 = await fakeRequest('/hoge');
    console.log(data1);
}

makeRequest();
```
#### resolveされた時の値を取得するには？


Promiseの場合は、.then((data)=> で取得することができました。

async awaitを使用する場合は、
awaitした関数の左側に変数を定義する形で取得することができます。

fakeRequestがresolveした値がdata1の中に入ってくれます。

```text:出力結果（resolveされた場合）
ダミーデータ(/hoge)
```

## Promiseがrejectされた時の値の使用

Promiseの時にエラーを取得する場合は、.catchを使用しました。

async awaitでエラーを取得する場合には、
try、catchを使用します。

```js

async function makeRequest() {
    try {
        const data1 = await fakeRequest('/hoge');
        console.log(data1);
    } catch (e) {
        console.log('エラー発生!!');
        console.log(e);
    }
}

makeRequest()
```

1. async function makeRequest関数を作成。
2. tryには、 resolveされた時の処理を記載する
3. catchには、rejectされた時の処理を記載する 

```text:出力結果：
ダミーデータ(/hoge) // （resolveされた場合）

エラー発生!!
コネクションタイムアウト //(rejectされた場合)

```