雰囲気で理解する 非同期処理 async/await とは 

# 非同期処理 async/await

分かりやすさ重視、所々本質とは違うと思います。理解の備忘録としてご了承ください。

# 同期処理と非同期処理

コードを実行する際に

同期処理：上から順に実行される通常の実行

非同期処理：一部処理を退避させて別処理させる。

# Promiseについて

Promise：**関数の返り値としてアタッチ**される、**関数の種類、関数の返り値の型**と思ってもいいかも。処理の実行を約束する。失敗やその途中経過や結果を返す。

**返される結果について**
- pending(実行中)
- settled(実行完了)
    →settled(実行完了)の中身
    - rejected(失敗)
    - fulfilled(成功)

**・Promise のコンストラクタ の 第一引数 / 第二引数 コールバック について**
``` js
const promise = new Promise(function(resolve, reject)=>{
  if (True) {
    resolve("resolveの時の内容");
  } else {
    reject("rejectの時の内容");
  }
  console.log("関数は止まらない");
});


promise
  .then((value) => console.log("resolveの内容:", value))
  .catch((reason) => console.error("rejectの内容:", reason));
```

Promiseのコンストラクタの 第一引数 / 第二引数 に(resolve,reject)を設定し

関数内に
成功時（fulfilledの内容）→resolve(“返したい内容“)
失敗時（rejectedの内容）→reject(“返したい内容“)
を記述する。
なお、resolve,rejectを通過しても関数の実行自体は止まらない。


# asyncについて

関数の頭につけると返り値が強制的にpromiseとなる。

asyncの内部の関数は**awaitが使用できるようになる**。

# **実行の結果を待ちたいとき**

基本的に「Promise/then」 or 「async/await」の組み合わせが多い。

※thenとawaitを同居させることもできるが最初のうちは使わない方が理解がしやすいはず。

## Promise/then使用時

Promise/thenで繋いで記述(※同様の概念がawait。then≒await)

```jsx
//axiosはapi通信に関するライブラリで、axios.postは返り値がpromiseとなる関数
axios.post("url~~~~~~") 

.then((res)=>{
console.log(res);
const test = axios.post(res.url)
return test
}) 

.then((test)=>{
console.log(test)
})
```

---

## async/await使用時

async/await を用いて記述。**awaitを使うときはasyncとセット**。awaitはasync関数の中身でしか使用できない。

await の後ろにはpromiseを返す関数がくる( await {promise関数})。

余談）async自体が関数の返り値をpromise化するのに対して、awaitの後ろにもPromise関数を置かないといけないのイメージしづらい(入れ子みたいになる)。まあawaitみたいに実行に時間がかかって待たせたい処理は大体Promise的な処理だし、そうじゃなくてもPromise化しときたいよねって感じ。

**await以降の記述はawaitの処理が終わるまで実行されない**。（thenと同じイメージ。）

言い換えるとawaitで一旦止まる。

```jsx
//このfunction Testの頭にasyncをつけたおかげでTest関数の返り値はpromiseとなる。
async function Test()=>{ 
//axiosはapi通信に関するライブラリで、axios.postは返り値がpromiseとなる関数 
const res = await axios.post("url~~~~~~")
console.log(res);
const test = await axios.post(res.url)
console.log(test)
}

//上記では関数を宣言しただけなので別途実行する必要あり
Test()
```

こっちの方がスッキリ書ける。

---

# Promise.all() promise系の同時処理を行いたい場合

複数のPromise系処理を同時に行いたい場合（並列処理したい場合）はPromise.allを使う。

```jsx
Promise.all( [ promise関数1,promise関数2,… ] )
```

---

例えばapi通信を5個同時に行いたい場合など

```jsx
await axios.post(URL1)
await axios.post(URL2)
await axios.post(URL3)
await axios.post(URL4)
await axios.post(URL5)
```


とすると一々実行完了まで待つのでかかる時間は

URL1 + URL2 + URL3 + URL4 +URL5

となるがPromise.allを使うと

```jsx
Promise.all( [ axios.post(URL1), axios.post(URL2),axios.post(URL3),axios.post(URL4),axios.post(URL5) ] )
```

URL1〜5のpost通信を同時に行う（並列処理する）ため、

かかる時間はURL1~5のうち最も長い時間のみになる。(MAX(URL1,…,URL5))

エラーハンドリングは.thenと.catchで行う。

``` jsx
Promise.all(promise関数1,promise関数2)   
.then((data)=>{
   //promise関数1の結果
   console.log(data[0])   
   //promise関数2の結果
   console.log(data[1])
   console.log("全て成功")   
})   
.catch((err)=>{   
    console.log("実行したうちのどれか一つでも失敗")  
})
```

結果はそれぞれthenの引数に格納されてたりする。const data = Promise.all()とすると**データを外に取り出せたりする。**

---

# その他

### 歴史的な流れ

非同期処理の歴史的には

setTimeoutによるcallback地獄

→promise / thenが 発明されて可読性向上

→async / await によりさらに可読性向上

のイメージ。

## 参考記事

https://makky12.hatenablog.com/entry/2020/01/11/175931

https://makky12.hatenablog.com/entry/2020/07/24/191419

https://zenn.dev/estra/books/js-async-promise-chain-event-loop/viewer/g-epasync-resolve-reject