Node.js fs.readdir 再帰ディレクトリ検索 質問する

Node.js fs.readdir 再帰ディレクトリ検索 質問する

fs.readdir を使用した非同期ディレクトリ検索について何かアイデアはありますか? 再帰を導入して、次に読み取るディレクトリを指定してディレクトリ読み取り関数を呼び出すことができることはわかっていますが、非同期ではないのではないかと少し心配です...

何かアイデアはありますか?ノードウォークこれは素晴らしいですが、readdirのように配列内のファイルだけを取得することはできません。

次のような出力を探しています...

['file1.txt', 'file2.txt', 'dir/file3.txt']

ベストアンサー1

これを実現するには、基本的に 2 つの方法があります。非同期環境では、シリアルとパラレルの 2 種類のループがあることに気付くでしょう。シリアル ループは、1 つの反復が完了するのを待ってから次の反復に進みます。これにより、ループのすべての反復が順番に完了することが保証されます。パラレル ループでは、すべての反復が同時に開始され、1 つの反復が別の反復より先に完了する場合がありますが、シリアル ループよりもはるかに高速です。したがって、この場合は、ウォークがどのような順序で完了するかは問題ではなく、完了して結果が返される (順番に結果を返す必要がある場合を除く) 限り、パラレル ループを使用する方がよいでしょう。

並列ループは次のようになります。

var fs = require('fs');
var path = require('path');
var walk = function(dir, done) {
  var results = [];
  fs.readdir(dir, function(err, list) {
    if (err) return done(err);
    var pending = list.length;
    if (!pending) return done(null, results);
    list.forEach(function(file) {
      file = path.resolve(dir, file);
      fs.stat(file, function(err, stat) {
        if (stat && stat.isDirectory()) {
          walk(file, function(err, res) {
            results = results.concat(res);
            if (!--pending) done(null, results);
          });
        } else {
          results.push(file);
          if (!--pending) done(null, results);
        }
      });
    });
  });
};

シリアル ループは次のようになります。

var fs = require('fs');
var path = require('path');
var walk = function(dir, done) {
  var results = [];
  fs.readdir(dir, function(err, list) {
    if (err) return done(err);
    var i = 0;
    (function next() {
      var file = list[i++];
      if (!file) return done(null, results);
      file = path.resolve(dir, file);
      fs.stat(file, function(err, stat) {
        if (stat && stat.isDirectory()) {
          walk(file, function(err, res) {
            results = results.concat(res);
            next();
          });
        } else {
          results.push(file);
          next();
        }
      });
    })();
  });
};

ホーム ディレクトリでテストするには、次のようにします (警告: ホーム ディレクトリに多くのデータがある場合、結果リストは膨大になります):

walk(process.env.HOME, function(err, results) {
  if (err) throw err;
  console.log(results);
});

編集: 例を改善しました。

おすすめ記事