Nodejs异步递归文件夹大小
Posted
技术标签:
【中文标题】Nodejs异步递归文件夹大小【英文标题】:Nodejs asynchronous recursive folder size 【发布时间】:2016-03-05 03:59:59 【问题描述】:您好,我对 javascript、Nodejs 及其异步世界还很陌生,我正在尝试以异步方式获取文件夹列表的大小(如 du 命令)。比如:
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);
我期望以异步方式从回调中获取结果,因此当 du
完成文件夹 N 时,回调会打印出文件夹 N 的结果。
我尝试使用来自 here 的这段代码,它使用了柯里化和闭包:
//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
我在使用 闭包 的代码中遇到的问题是,如果在第一个调用仍在进行时对 du
的第二次调用开始,那么一切都会因为闭包重复使用而变得一团糟total、file_counter 和 async_running 的当前值。
【问题讨论】:
感谢您使用 Promise 的回答,但首先我想了解异步 nodejs(使用回调)的基本概念,然后使用诸如 Promise 或 Asynch 之类的高级库。 【参考方案1】:我觉得回调有点麻烦,所以使用Promise
它仍然是异步的,希望cmets澄清事情......
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));
【讨论】:
【参考方案2】:首先我认为你必须学习如何处理多个异步操作之前你必须寻找 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);
);
)
)
);
使用此代码,您可以递归查找每个子目录
【讨论】:
以上是关于Nodejs异步递归文件夹大小的主要内容,如果未能解决你的问题,请参考以下文章