こんにちは、ライターのマサトです!
今回は、Promiseを使った非同期処理を簡潔に記述することができる「async / await」について学習をしていきましょう!
この記事では、
- 「async / await」とは?
- 「async / await」の使い方
- 「async / await」の並列処理
などの基本的な内容から、応用的な使い方に関しても解説していきます。この記事で、「async / await」をしっかり学習して自分のスキルアップを目指しましょう!
「async/await」とは?
それでは、まず最初に「async / await」について基本的な知識から身につけていきましょう!
「async / await」は、Promiseによる非同期処理をより簡潔に効率よく記述できるのが大きな特徴です。「非同期処理」は時間の掛かる処理の結果を待たずにすぐ次の処理を実行できる仕組みですが、Promiseを使うことで簡単に実現できます。
ただ、Promiseの場合は「then」を使ってチェーンを繋いでいくので、少し単調なコードになりやすいわけです。例えば、複数のPromise処理を「then」を使って実行すると以下のようになります。
getDate() .then(function(data) { return getYear(data) }) .then(function(year) { return getSomething(year) }) .then(function(item) { getAnotherThing(item) })
場合によっては「Promise.all()」を使うことで、もう少しだけスマートに記述できますがそれでも「then」を使った記述は必須です。
そこで、もう少し分かりやすく効率の良い書き方ができる「async / await」を使う方法について本記事で学んでいきましょう! ちなみに、Promiseについてまだ不安のある方は次の記事で基本から応用まで解説しているのでぜひ参考にしてみてください!
「async/await」の使い方
この章では、基本的な「async / await」の使い方について見ていきましょう! 一般的な構文から実際のプログラミング処理について学んでいきます。
基本的な構文と書き方について
まずは、もっとも基本となる構文について見ていきましょう! 「async」は「function」の前に記述するだけで非同期処理を実行できる関数を定義できます。
async function() { }
このようにasyncを記述しておくと、この関数はPromiseを返すようになります。また、「await」はPromise処理の結果が返ってくるまで一時停止してくれる演算子となります。
await Promise処理
このようにPromise処理が記述された関数の前に「await」を記述するだけで、結果が返ってくるまで一時停止してくれるわけです。ただし、「await」は「async」で定義された関数の中だけでしか使えないので注意しておきましょう!
また、このような理由から「async / await」はペアで一緒に使われることが多いわけです。
「async/await」で非同期処理を記述する方法
それでは、実際のプログラミング方法を見ていきましょう! まずは、以下のようなPromise処理があるとします。
function myPromise(num) { return new Promise(function(resolve) { setTimeout(function() { resolve(num * num) }, 3000) }) }
この例では、わざと3秒の時間が掛かる処理をPromise内に記述しているのが分かります。そして、引数で受け取った値(num)を2乗した結果を「resolve」で返す単純な仕組みとなっています。これを「then」を使わずに「async / await」を利用すると次のようになります。
async function myAsync() { const result = await myPromise(10); console.log(result); } myAsync();
実行結果
100
この例では、asyncを付与することで非同期処理の関数を作成していますね。その関数内でPromise処理を記述している「myPromise()」の前に「await」を付与しているのが分かります。
これにより、3秒後に結果が返ってくるPromise処理を一時的に待つことになり、結果を取得した瞬間に関数内の処理が続行されるのです。実行結果には引数に与えた「10」が2乗された値「100」が取得できていますね。
「then」を使わずに非同期処理を複数実行する方法
今度は、複数の非同期処理を実行する方法について見ていきましょう! まずは、従来のPromiseを利用した方法として「then」を使った場合を見てみます。
myPromise(10).then(function(data) { console.log(data); return myPromise(100) }).then(function(data) { console.log(data); return myPromise(1000) }).then(function(data) { console.log(data); })
この例では、先ほど利用した3秒の時間が掛かるPromise処理を繋げて実行しています。「then」を利用することでメソッドチェーンによる記述になっているのが特徴です。また、Promise処理を繋げる場合は「then」の最後に実行するPromise関数をreturnするのを忘れないようにしなければいけません。
それでは、同じ処理を「async / await」で実行するとどうなるか見てみましょう!
async function myAsyncAll() { console.log(await myPromise(10)); console.log(await myPromise(100)); console.log(await myPromise(1000)); } myAsyncAll();
実行結果
[100 10000 1000000]
まず、非常にコードがすっきりして把握しやすくなっているのが分かりますね。asyncが付与された関数内で、実行する予定のPromise処理をすべて「await」を付けて実行しています。これにより、上から順番にPromiseの結果が返ってきてコンソールへ出力されるというわけです。
「async/await」の並列処理
この章では、「async / await」を使った並列処理の方法について見ていきましょう! 主に、Promiseを使った場合との違いについて詳しく学んでいきます。
Promise.all()を使った並列処理との違い
まずは、従来のPromise.all()を使った方法を確認してみましょう!
Promise.all([ myPromise(10), myPromise(100), myPromise(1000) ]).then(function(data) { console.log(data); })
この例では、「myPromise()」の引数違いを3つ同時に実行しています。最後に「then」で実行結果を配列として出力するという流れになっていますね。これと同様の処理を「async / await」で実行すると次のようになります。
async function myAsyncAll() { const r1 = myPromise(10); const r2 = myPromise(100); const r3 = myPromise(1000); console.log(await r1, await r2, await r3); } myAsyncAll();
まず最初に、実行予定のPromise処理をすべて起動させて変数に格納します。そのあとに「await」を付与することですべてのPromise処理を並列に動かして結果を取得することができるわけです。
まとめ
今回は、Promiseを使った非同期処理を簡潔に記述できる「async / await」について学習しました。最後に、もう一度ポイントをおさらいしておきましょう!
- asyncはfunctionの前に付与するだけでPromiseを返す非同期処理を定義できる
- awaitはasyncが付与された関数内でのみ実行することができる
- 並列処理を記述する場合は先にすべてのPromise処理を起動させておく
上記内容を踏まえて、ぜひ自分でもプログラミングに取り入れて活用できるように頑張りましょう!