2014-09-05 32 views
0

我想獲得包含在一個目錄中的唯一文件名列表,包括使用節點的子目錄,並且在組合每個回調的結果時遇到了一些麻煩。我想避免重複操作,如果我只從fs.stat回調登錄文件名,會發生什麼情況。Node.js與累加器異步目錄遍歷

var distinct = {}; 

function getNames(root) { 
    fs.readdir(root, function(err, list) { 
     list.forEach(function(file) { 
      file = root + '/' + file; 
      fs.stat(file, function(err, stat) { 
       if (!err && stat.isDirectory()) { 
        getNames(file); 
       } else { 
        distinct[path.basename(file)] = true; 
       } 
      }); 
     }); 
    }); 
} 

// perform various operations on unique filename list 
console.log(Object.keys(distinct)); 

當然這太早調用console.log()函數,並給出不希望的結果。我如何獲得一組文件名以進行工作;是否有使用異步方法進行此操作的好方法,即無需使用readdirSyncstatSync

+0

一個提示,使用'path.join(root,file)'而不是'root +'/'+ file' – naomik 2014-09-05 18:12:55

回答

1

異步模塊將成爲您的朋友。

var distinct = {}; 
function getNames(root, callback) { 
    fs.readdir(root, function(err, list) { 
     if (err) return callback(err); 

     async.each(list, function(file, done) { 
      fs.stat(file, function(stat) { 
       if (err) return done(err); 
       if (stat.isDirectory()) return getNames(file, done); 
       distinct[path.basename(file)] = true; 
       done(); 
      }); 
     }, function(err) { 
      // called when all done or error 
      callback(err, distinct); 
     }) 
    }); 
} 

然後你可以使用它像

getNames('path/to/dir', function(distinct) { 
    // logic 
}); 
1

我可能會建議使用promises

function getNames(root) { 
    readdir = Q.nfbind(fs.readdir); 
    stat = Q.nfbind(fs.stat); 
    return readdir(root) 
     .then(function(list) { 
      files = []; 
      for(var i = 0; i < list.length; i++) { 
       file = root + '/' + list[i]; 
       files.push(stat(file) 
        .then(function(stat) { 
         if (stat.isDirectory()) { 
          return getNames(file); 
         } else { 
          return path.basename(file); 
         } 
        }) 
       ); 
      } 
      return Q.all(files); 
     }); 
} 
getNames('someDir') 
    .then(console.log) 
    .catch(console.error);