async/await完全に理解した（JavaScript）

# きっかけ

最近Node.jsを触る機会があるが、言語を体系的に勉強してきたわけではないので、必要な機能から調べながら使っている。
あるとき一定時間待ってから次の処理を行うシーケンス的なことをしたいなと思って調べたところ、やりたいことは「非同期処理」と言われるようだ。次のようなサンプルコードが出てきた。

```javascript:コールバックを使う方法
const t0 = Date.now(); // 開始時刻を取得
console.log('開始: ' + (Date.now() - t0)); // 経過時刻をあわせて出力
setTimeout(function() {
    console.log('1秒後に実行されるはず: '+ (Date.now() - t0)); // 経過時刻をあわせて出力
}, 1000);
```

```:出力
開始: 0
1秒後に実行される: 1004
```

**あーそーゆーことね完全に理解した**（画像は脳内補完願います）
よし、ちゃんと1秒後に実行された。
じゃあ処理を2段階にしてみよう。

```javascript:コールバックを使う方法2
const t0 = Date.now();
console.log('開始: ' + (Date.now() - t0));
setTimeout(function() {
    console.log('1秒後に実行されるはず: '+ (Date.now() - t0));
    setTimeout(function() {
        console.log('2秒後に実行されるはず: '+ (Date.now() - t0));
    }, 1000);
}, 1000);
```

```:出力
開始: 0
1秒後に実行されるはず: 1003
2秒後に実行されるはず: 2004
```

**あーそーゆーことね完全に理解した**（画像は脳内補完願います）
じゃあ10個に増やしてみよう。

```javascript:コールバックを使う方法4
const t0 = Date.now();
console.log('開始: ' + (Date.now() - t0));
setTimeout(function() {
    console.log('1秒後に実行されるはず: '+ (Date.now() - t0));
    setTimeout(function() {
        console.log('2秒後に実行されるはず: '+ (Date.now() - t0));
        setTimeout(function() {
            console.log('3秒後に実行されるはず: '+ (Date.now() - t0));
            setTimeout(function() {
                console.log('4秒後に実行されるはず: '+ (Date.now() - t0));
                setTimeout(function() {
                    console.log('5秒後に実行されるはず: '+ (Date.now() - t0));
                    setTimeout(function() {
                        console.log('6秒後に実行されるはず: '+ (Date.now() - t0));
                        setTimeout(function() {
                            console.log('7秒後に実行されるはず: '+ (Date.now() - t0));
                            setTimeout(function() {
                                console.log('8秒後に実行されるはず: '+ (Date.now() - t0));
                                setTimeout(function() {
                                    console.log('9秒後に実行されるはず: '+ (Date.now() - t0));
                                    setTimeout(function() {
                                        console.log('10秒後に実行されるはず: '+ (Date.now() - t0));
                                    }, 1000);
                                }, 1000);
                            }, 1000);
                        }, 1000);
                    }, 1000);
                }, 1000);
            }, 1000);
        }, 1000);
    }, 1000);
}, 1000);
```

**いやよく見たらクソむかつく**（画像は脳内補完願います）

なんだこのネストの嵐は。
調べてみると、これはJavaScript界隈で言われている**コールバック地獄**というやつらしい。
更に調べてみると、イマドキのJavaScriptにはコールバック地獄を解消する方法が用意されているということがわかった。ですよねー。

# Promise と async/await

コールバック地獄を解消する方法は2種類ほどあるらしい。
1. Promiseを使う方法
2. async/awaitを使う方法
後者のasync/awaitの方が新しくてイマドキらしい。ということで前者のPromiseは飛ばしても大丈夫かな。
というわけで、async/awaitの概要を調べてみた。

引用：[async/awaitを使ったモダンな非同期処理 - Qiita](https://qiita.com/rana_kualu/items/f3dfcb8e7ef0cc9955d6)
> リピートミー。「async/awaitはPromiseで作られている」。

！！？？ 

> async関数はPromiseを返します。
> この関数を呼び出すときにawaitを付けると、このコードはPromiseがresolvedかrejectedを返すまで停止します。

**async/awaitを完全に理解するには、結局Promiseを理解しないといけないらしい**

# async/awaitの完全理解

この辺をじっくり読んでいろいろコードを書いて試した。

- [async/await 入門（JavaScript） - Qiita](https://qiita.com/soarflat/items/1a9613e023200bbebcb3)

- [async function - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/async_function)

## コードと解説

先程の10回待つ処理をasync/awaitを使って書くとこうなる。

```javascript:async/awaitを使ったコード
const t0 = Date.now();
console.log('開始: ' + (Date.now() - t0));
asyncCall();

function wait1sec() {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve();
        }, 1000);
    });
}

async function asyncCall() {
    await wait1sec();
    console.log('1秒後に実行されるはず: '+ (Date.now() - t0));
    await wait1sec();
    console.log('2秒後に実行されるはず: '+ (Date.now() - t0));
    await wait1sec();
    console.log('3秒後に実行されるはず: '+ (Date.now() - t0));
    await wait1sec();
    console.log('4秒後に実行されるはず: '+ (Date.now() - t0));
    await wait1sec();
    console.log('5秒後に実行されるはず: '+ (Date.now() - t0));
    await wait1sec();
    console.log('6秒後に実行されるはず: '+ (Date.now() - t0));
    await wait1sec();
    console.log('7秒後に実行されるはず: '+ (Date.now() - t0));
    await wait1sec();
    console.log('8秒後に実行されるはず: '+ (Date.now() - t0));
    await wait1sec();
    console.log('9秒後に実行されるはず: '+ (Date.now() - t0));
    await wait1sec();
    console.log('10秒後に実行されるはず: '+ (Date.now() - t0));
}
```

```:出力
1秒後に実行されるはず: 1009
2秒後に実行されるはず: 2013
3秒後に実行されるはず: 3015
4秒後に実行されるはず: 4019
5秒後に実行されるはず: 5022
6秒後に実行されるはず: 6028
7秒後に実行されるはず: 7029
8秒後に実行されるはず: 8036
9秒後に実行されるはず: 9042
10秒後に実行されるはず: 10046
```



# おまけ

`async` は「エイシンク」と読むらしい。「アシンク」だと思ってた。
`await` は「アウェイト」で良いらしい。