Nodejs异步递归文件夹大小

时间:2015-12-01 09:27:39

标签: javascript node.js asynchronous closures currying

您好我是Javascript,Nodejs及其异步世界的新手,我试图以异步方式获取文件夹列表(如du命令)的大小。类似的东西:

ddmmyy hh:mm:ss node-xx PROCESS LOGLEVEL MESSAGE

我期待的是以asyinch的方式从回调中获得结果,所以当du = function(directory, callback){ ... } displaySum = function(err, result) { if(!err) {console.log(result);} } var folders = ['/folder1', '/folder2', '/folder3']; for (var i = 0; i < folders.length; i++) { du(folders[i], displaySum); } 完成folderN时,回调会打印出folderN的结果。

我尝试使用here中使用currying和closures的代码:

du

我使用 Closures 的代码所遇到的问题是,如果第一次调用仍然在进行时对//Pseudocode duAsync4 = (dir,cb) -> total = 0 file_counter = 1 #starts at one because of the initial directory async_running = 0 again = (current_dir) -> fs.lstat current_dir, (err, stat) -> if err then file_counter--; return if stat.isFile() file_counter-- total += stat.size else if stat.isDirectory() file_counter-- async_running++ fs.readdir current_dir, (err,files) -> async_running-- if err then return #console.log err.message file_counter += files.length for file in files again path.join(current_dir, file) else file_counter-- if file_counter is 0 and async_running is 0 cb(null, total) again dir 的第二次调用开始,那么一切都搞砸了,因为关闭了 - 使用total,file_counter和async_running的当前值。

2 个答案:

答案 0 :(得分:2)

我发现回调有点麻烦,所以使用Promise它仍然是异步的,希望评论澄清事情...

var fs = require('fs')
  , path = require('path');

function getSize(dirPath){      
  return getStat(dirPath).then(function(stat){  
    if(stat.isFile()){  // if file return size directly
      return stat.size;
    }else{
      return getFiles(dirPath).then(function(files){    // getting list of inner files
        var promises = files.map(function(file){
          return path.join(dirPath, file);  
        }).map(getSize);    // recursively getting size of each file
        return Promise.all(promises);   
      }).then(function(childElementSizes){  // success callback once all the promise are fullfiled i. e size is collected 
          var dirSize = 0;
          childElementSizes.forEach(function(size){ // iterate through array and sum things
              dirSize+=size;
          });
          return dirSize;
      });
    }    
  });
}

// promisified get stats method
function getStat(filePath){
  return new Promise(function(resolve, reject){
    fs.lstat(filePath, function(err, stat){
      if(err) return reject(err);
      resolve(stat);
    });
  });
}

// promisified get files method
function getFiles(dir){
  return new Promise(function(resolve, reject){
    fs.readdir(dir, function(err, stat){
      if(err) return reject(err);
      resolve(stat);
    });
  });  
}

// example usage
getSize('example dir').then(function(size){
    console.log('dir size: ', size);
}).catch(console.error.bind(console));

答案 1 :(得分:0)

首先,我认为你必须先学习如何处理多个异步操作,你必须寻找Promise或像async js这样的库。

接下来你可以尝试这样的事情:

var fs = require('mz/fs');

var myDir = './';

readdir(myDir)
function readdir(dir) {
  fs.readdir(dir)
    //mz fs transform all fs functions to promises
    .then(function(files) {

    //wait each promises
    return Promise.all(
      files.map(function(file) {

        return fs.lstat(file)
          .then(function(stats) {

            //the function is recursive
            if (stats.isDirectory())
              return readdir(file);
          });
      })
    )
  });
}

使用此代码,您可以递归查找每个子目录