3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

async/await完全に理解した(JavaScript)

Posted at

きっかけ

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

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

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

コールバックを使う方法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個に増やしてみよう。

コールバックを使う方法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

リピートミー。「async/awaitはPromiseで作られている」。

!!??

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

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

async/awaitの完全理解

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

コードと解説

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

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 は「アウェイト」で良いらしい。

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?