今回は、Node.jsで非同期処理を効率よく記述できるasync パッケージと、標準で提供されているasync / awaitについて学習をしていきましょう!
asyncの使い方を知りたい
asyncのメソッドをどのように扱えばいいか知りたい
このような内容も含めて、本記事では以下のような構成で解説していきます!
- 【基礎】「async」の使い方
- 【実践】非同期処理の並列実行
- 【実践】async / awaitについて
- 【まとめ】asyncの使い方まとめ
この記事で、asyncをしっかり学習してスキルアップを目指していきましょう!ちなみに、そもそも非同期処理がどのようなものかを知りたい方は以下の記事で詳しくまとめているので参考にしてみてください!
「async」の使い方
この章では、Node.js向けに提供されている「async」パッケージの使い方について見ていきましょう! 主に、asyncの導入や各種メソッド(waterfall / series)の使い方について学んでいきます。
asyncの導入と基本的な書き方
まずは、Node.jsでasyncを使えるように準備をしていきましょう。npmを使って以下のようにasyncのパッケージを簡単に導入できます。
$ npm install async
インストールしたら、次のようにrequire()で使える状態にしておきます。
var async = require('async');
これで準備は完了です! asyncはいくつか提供されているメソッドを次のように記述することで非同期処理を簡潔に記述できるようにしてくれます。
async.メソッド名([関数, 関数, 関数・・・], 関数);
メソッドの第1引数に配列もしくはオブジェクトで複数の関数処理を記述することで非同期処理が実行されていきます。第2引数の関数処理でエラーハンドリングや結果を取得するのが基本となります。
seriesによる非同期処理
それでは、実際にasyncを使ったプログラミングをしてみましょう! まずは一般的な「series」メソッドを使って複数の非同期処理を順番に実行してみます。次のサンプル例を見てください!
async.series([ function(callback) { callback(null, '一番目'); }, function(callback) { callback(null, '2番目'); }, function(callback) { callback(null, '3番目'); } ], function (err, result) { console.log(result); });
実行結果
[ '1番目', '2番目', '3番目' ]
async.series()の第1引数に配列で3つの関数が記述されていることに注目してください! それぞれの関数にはコールバックが設定されており、第2引数に指定した値がスタックされていくようになっています。
つまり、この例ではそれぞれのコールバックで文字列が1つずつスタックされており、最後の関数処理でその文字列を配列として取得できるわけです。最後の関数処理では、何らかのエラーが起きたときの情報も取得できるようになっています。
waterfallによる非同期処理
次に、waterfallメソッドについても合わせて見ていきましょう! waterfallの使い方はseriesメソッドとほとんど同じように扱えるのですが、コールバックに設定した値を次の関数処理で利用できるのが大きな特徴でしょう。
次のサンプル例を見てください!
async.waterfall([ function(callback) { callback(null, '1番目', '2番目'); }, function(arg1, arg2, callback) { callback(null, arg1 + arg2 + '3番目'); }, function(arg1, callback) { callback(null, arg1); } ], function (err, result) { console.log(result); });
実行結果
1番目2番目3番目
1つ目の関数内で記述しているコールバックで、「1番目」「2番目」という文字列を設定している点に注目してください! この文字列の値が次の関数へ引き渡されて、引数「arg1」「arg2」へそれぞれ格納されます。
なので、直前の関数の値を次の関数で再利用することができるわけですね。最後の関数処理では、一番最後に実行された関数の結果を取得できるのが実行結果からも分かります。
非同期処理の並列実行
この章では、asyncを使って非同期処理を並列に実行する方法について見ていきましょう! 主に、parallelメソッドを使ったプログラミング手法について学んでいきます。
parallelによる非同期処理
非同期処理の並列実行というのは、簡単に言うと複数の非同期処理を同時に実行してすべての処理が完了した結果を取得する方法になります。これを実現するには「parallel」メソッドを使うのが簡単です。
例えば、分かりやすいようにsetTimeout()を使って、わざと異なる時間が掛かる処理を作成してみましょう!
async.parallel([ function(callback) { setTimeout(function() { callback(null, '3秒後の文字列'); }, 3000); }, function(callback) { setTimeout(function() { callback(null, '1秒後の文字列'); }, 1000); } ],function(err, results) { console.log(results); });
実行結果
[ '3秒後の文字列', '1秒後の文字列' ]
この例では、3秒間必要な関数と1秒間必要な関数が記述されています。普通はこのような関数を実行すると、それぞれ結果を得られるタイミングが異なりますよね?
しかし、parallelを利用するとすべての関数が終了してから結果をまとめて取得できるというのが大きな特徴になります。例えば、複数のサーバーからデータを取得して最後にまとめて出力したいようなケースで便利に活用できるでしょう。
async/awaitについて
これまでは「async」パッケージを導入した非同期処理の使い方について学習してきました。
しかしながら、パッケージを利用せずとも最新のNode.jsでは「async / await」による非同期処理が標準で使えるようになっています。例えば、次のようなPromise処理があるとします。
unction myPromise(num) { return new Promise(function(resolve) { setTimeout(function() { resolve(num * num) }, 3000) }) }
この例では、3秒後に結果を返すPromise処理となっていますね。これをasync / awaitを使って非同期処理を行うと次のようになります!
async function myAsync() { var result = await myPromise(10); console.log(result); } myAsync();
まず、関数を記述する前にasyncを付与している点に注目しましょう。これにより関数内でawaitを使うことができます。awaitはPromise処理の結果を取得できるまで一時的に待機してくれるので、この例では3秒後に処理が完了するというわけです。
このasync / awaitについて、さらに応用的な活用方法や並列実行などを学習したい方は次の記事で体系的にまとめているので参考にしてみてください!
asyncの使い方まとめ
最後に、asyncパッケージを使った非同期処理の基本的な使い方についてまとめておきます。複数の非同期処理を順番に実行していく場合は「series」メソッドを使って次のように記述します。
async.series([ function(callback) { callback(null, '一番目'); }, function(callback) { callback(null, '2番目'); }, function(callback) { callback(null, '3番目'); } ], function (err, result) { console.log(result); });
それぞれの関数内で実行されるコールバックに指定した値が、1つずつスタックされていき最後にまとめて値を取得できるのが特徴です。
次に、類似メソッドとしてwaterfallによる非同期処理は次のように記述します。
async.waterfall([ function(callback) { callback(null, '1番目', '2番目'); }, function(arg1, arg2, callback) { callback(null, arg1 + arg2 + '3番目'); }, function(arg1, callback) { callback(null, arg1); } ], function (err, result) { console.log(result); });
seriesメソッドと違い、それぞれのコールバック関数に設定した値は次の関数処理内で再利用できるのが特徴です。最後に取得できる「result」は、一番最後に実行された関数の結果となる点に注意しましょう。
まとめ
今回は、Node.jsで効率よく非同期処理を記述できる「async」について学習しました。最後に、もう一度ポイントをおさらいしておきましょう!
- Node.jsではパッケージとして導入できるasyncと標準で提供されているasyncがある
- 非同期処理を順番に実行するにはseries / waterfallメソッドを使う
- 非同期処理の並列実行についてはparallelメソッドを使う
上記内容を踏まえて、ぜひ自分でもプログラミングに取り入れて活用できるように頑張りましょう!