Javascript 记录使用异步回调计算的总值

Javascript 记录使用异步回调计算的总值,javascript,node.js,Javascript,Node.js,如果我编写如下代码,每次添加文件时,我都会得到总的btye size值。在fs.stat回调中计算总文件大小后,如何仅注销总文件大小 var fs=require('fs'); var totalBytes=0; 函数calcTotalSize(){ //我读目录中的文件 fs.readdir(“.”),函数(错误,文件){ forEach(函数(文件名、索引){ fs.stat(“./”+文件名,函数(err,stats){ totalBytes+=stats.size; console.l

如果我编写如下代码,每次添加文件时,我都会得到总的btye size值。在fs.stat回调中计算总文件大小后,如何仅注销总文件大小

var fs=require('fs');
var totalBytes=0;
函数calcTotalSize(){
//我读目录中的文件
fs.readdir(“.”),函数(错误,文件){
forEach(函数(文件名、索引){
fs.stat(“./”+文件名,函数(err,stats){
totalBytes+=stats.size;
console.log(totalBytes);//与此类似,它记录文件数组中每个项的更新总数
});    
});
});
//--注销totalBytes--
}

calcTotalSize()您可以使用3个选项中的任意一个(我已按偏好顺序排列):

  • 使用
    promises
    在计算所有统计数据时获取回调

  • 使用
    fs.statSync

  • 跟踪已读取的文件数量,并在达到文件总数时输出总和

  • 由于23非常简单,我将向您展示如何使用promise库(有类似的库)实现1,应该如下所示:

    fs.readdir(".",function(err,files){
            var promises = [];
    
            files.forEach(function(filename,index) {
                var fsStatPromise = Q.nfcall(fs.stat, "./" + filename);
                promises.push(fsStatPromise);    
            });
    
            Q.all(promises).then(function(results) { 
                var total = results.reduce(function(a, b) {
                    return a.size + b.size;
                });
                console.log(total); 
            }, function(err) {
               console.log(err);
            });
        });
    

    在这里使用
    的好处是,与
    fs.statSync
    相比,使用
    的好处是不会降低
    异步io
    的性能,这将根据您读取的文件数量而有所不同……

    您遇到这个问题,因为
    readdir
    stat
    都是异步函数。解决此问题的最简单方法是使用
    readdirSync
    statSync
    您可以跟踪读取的总文件,例如:

    var fs = require('fs');
    var totalBytes = 0;
    var filesReaded = 0;
    
    function calcTotalSize(){
        fs.readdir(".",function(err,files){
    
            files.forEach(function(filename,index) {
    
                fs.stat("./" + filename,function(err,stats){
                    totalBytes += stats.size;
                    if (++filesReaded === files.length)
                      console.log(totalBytes); // log only when all the files were readed
                });    
            });
        });
    }
    
    calcTotalSize();
    

    要在使用async fs.stat()完成时打印出总数,您需要一些可以控制异步流的东西,例如async模块(不要忘记安装它:“npm install async”)。下面是使用async.each()修改的代码:


    谢谢Daniel非常详细的回答!本,谢谢你的解决方案。为了提高我的理解,eachCb(null)的含义是什么?它是异步的。each()的回调。循环的每次迭代都需要调用它,以通知async.each()继续。如果不调用此回调,async.each()将不会继续处理其余项(文件)。每个参数为null的(null)表示没有错误,并继续下一次迭代。如果传入非空/未定义的值。each()将停止处理其余项。因此,如果fs.stat()在回调中返回一个错误(err),并且您不想继续,则调用eachCb(err),而不是eachCb(null)/eachCb()。
    var fs = require('fs');
    var async = require('async');
    
    function calcTotalSize(){
        var totalBytes = 0;
        //I read the files in the dir
        fs.readdir(".",function(err,files){
            async.each(files, function(filename, eachCb) {
                fs.stat("./" + filename,function(err,stats){
                    totalBytes += stats.size;
                    eachCb(null);
                });
            }, function(err) {
                console.log('DONE: %d', totalBytes);
            });
        });
    }
    
    calcTotalSize();