Node.jsで配列の全ての要素に対して非同期的な処理を実行する
目次
配列の全ての要素に対して非同期的な処理を実行するにはasync
モジュールの下のような関数を使用します。
async.each
関数async.eachLimit
関数async.eachSeries
関数async.eachOf
関数async.eachOfLimit
関数async.eachOfSeries
関数
処理において要素の値のみが必要である場合にはasync.each
関数、async.eachSeries
関数、async.eachLimit
関数の何れかを使用し、要素のインデックスも必要である場合にはasync.eachOf
関数、async.eachOfSeries
関数、async.eachOfLimit
関数の何れかを使用します。
また、処理を完全に並列的に実行したい場合にはasync.each
関数かasync.eachOf
関数を使用し、並列的に実行する処理の最大数を指定して実行したい場合にはasync.eachLimit
関数かasync.eachOfLimit
関数を使用し、直列的に実行したい場合にはasync.eachSeries
関数かasync.eachOfSeries
関数を使用します。
なお、処理の実行中にエラーが発生しても既に開始している他の要素に対する処理の実行は続行しますので注意してください。しかし、まだ開始していない要素に対する処理の実行は行われません。
async.each関数とasync.eachSeries関数
var async = require('async');
async.each(['xxx', 'yyy', 'zzz'], function (item, callback) {
callback(null);
//or
callback(new Error('aaa'));
}, function (err) {
});
async.eachSeries(['xxx', 'yyy', 'zzz'], function (item, callback) {
callback(null);
//or
callback(new Error('aaa'));
}, function (err) {
});
第1引数
第1引数に配列を指定します。あるいは、配列以外のイテラブルを指定することもできます。
イテラブルとは?
第2引数
第2引数に配列の要素に対する処理を関数として指定します。
この関数の第1引数は配列の要素の値であり、第2引数はコールバック関数です。
処理が完了した場合や処理の実行中にエラーが発生した場合には必ずこのコールバック関数を呼び出さなければなりません。
このコールバック関数の第1引数にはエラーオブジェクト(エラーが発生しなかった場合にはnull
)を指定します。
第3引数
第3引数に配列の全ての要素に対して処理が完了したか、処理の実行中にエラーが発生した場合に呼び出されるコールバック関数を指定します。
この関数の第1引数はエラーオブジェクトです。
この引数は指定しなくても構いません。
async.eachLimit関数
async.eachLimit(['xxx', 'yyy', 'zzz'], 10, function (item, callback) {
callback(null);
//or
callback(new Error('aaa'));
}, function (err) {
});
async.each
関数やasync.eachSeries
関数とほぼ同じですが、第1引数と第2引数の間に並列的に実行する処理の最大数を指定します。
async.eachOf関数とasync.eachOfSeries関数
async.eachOf(['xxx', 'yyy', 'zzz'], function (item, index, callback) {
callback(null);
//or
callback(new Error('aaa'));
}, function (err) {
});
async.eachOfSeries(['xxx', 'yyy', 'zzz'], function (item, index, callback) {
callback(null);
//or
callback(new Error('aaa'));
}, function (err) {
});
async.each
関数やasync.eachSeries
関数とほぼ同じですが、第2引数の関数の第1引数と第2引数の間に配列の要素のインデックスが入ります。
async.eachOfLimit関数
async.eachOfLimit(['xxx', 'yyy', 'zzz'], 10, function (item, index, callback) {
callback(null);
//or
callback(new Error('aaa'));
}, function (err) {
});
async.eachLimit
関数とほぼ同じですが、第2引数の関数の第1引数と第2引数の間に配列の要素のインデックスが入ります。
サンプルコード1
async-each.js
var async = require('async');
var util = require('util');
var xs = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
async.eachSeries(xs, function (item, callback) {
setTimeout(function () {
util.log(item);
callback(null);
}, Math.random() * 1000);
}, function (err) {
if (err) {
console.error(err);
process.exit(1);
}
else {
async.each(xs, function (item, callback) {
setTimeout(function () {
util.log(item);
callback(null);
}, Math.random() * 1000);
}, function (err) {
if (err) {
console.error(err);
process.exit(1);
}
else {
async.eachLimit(xs, 2, function (item, callback) {
setTimeout(function () {
util.log(item);
callback(null);
}, Math.random() * 1000);
}, function (err) {
if (err) {
console.error(err);
process.exit(1);
}
});
}
});
}
});
使用パッケージ
- Async.js
npm install async
でインストールします。
実行結果
C:\work\node>node async-each.js
1 Jun 17:50:13 - 0
1 Jun 17:50:14 - 1
1 Jun 17:50:14 - 2
1 Jun 17:50:14 - 3
1 Jun 17:50:15 - 4
1 Jun 17:50:16 - 5
1 Jun 17:50:16 - 6
1 Jun 17:50:17 - 7
1 Jun 17:50:17 - 8
1 Jun 17:50:18 - 9
1 Jun 17:50:18 - 6
1 Jun 17:50:18 - 8
1 Jun 17:50:18 - 3
1 Jun 17:50:18 - 1
1 Jun 17:50:18 - 7
1 Jun 17:50:18 - 4
1 Jun 17:50:18 - 9
1 Jun 17:50:18 - 2
1 Jun 17:50:18 - 5
1 Jun 17:50:19 - 0
1 Jun 17:50:19 - 1
1 Jun 17:50:19 - 0
1 Jun 17:50:20 - 2
1 Jun 17:50:20 - 3
1 Jun 17:50:21 - 4
1 Jun 17:50:21 - 6
1 Jun 17:50:21 - 5
1 Jun 17:50:22 - 7
1 Jun 17:50:22 - 8
1 Jun 17:50:23 - 9