Quantcast
Channel: Node.jsタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 8875

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

$
0
0

きっかけ

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

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

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

コールバックを使う方法2
constt0=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
constt0=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を使ったコード
constt0=Date.now();console.log('開始: '+(Date.now()-t0));asyncCall();functionwait1sec(){returnnewPromise(resolve=>{setTimeout(()=>{resolve();},1000);});}asyncfunctionasyncCall(){awaitwait1sec();console.log('1秒後に実行されるはず: '+(Date.now()-t0));awaitwait1sec();console.log('2秒後に実行されるはず: '+(Date.now()-t0));awaitwait1sec();console.log('3秒後に実行されるはず: '+(Date.now()-t0));awaitwait1sec();console.log('4秒後に実行されるはず: '+(Date.now()-t0));awaitwait1sec();console.log('5秒後に実行されるはず: '+(Date.now()-t0));awaitwait1sec();console.log('6秒後に実行されるはず: '+(Date.now()-t0));awaitwait1sec();console.log('7秒後に実行されるはず: '+(Date.now()-t0));awaitwait1sec();console.log('8秒後に実行されるはず: '+(Date.now()-t0));awaitwait1sec();console.log('9秒後に実行されるはず: '+(Date.now()-t0));awaitwait1sec();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は「アウェイト」で良いらしい。


Viewing all articles
Browse latest Browse all 8875

Trending Articles