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

Log a total value calculated with async callback

本文关键字:计算 总价值 回调 异步 记录      更新时间:2023-09-26

如果我编写类似下面的代码,每次添加文件时,我将获得总btype大小值。我怎么能只注销文件的总大小,在它被计算在fs。统计回调?

var fs = require('fs');
var totalBytes = 0;
function calcTotalSize(){
    //I read the files in the dir
    fs.readdir(".",function(err,files){
        files.forEach(function(filename,index) {
            fs.stat("./" + filename,function(err,stats){
                totalBytes += stats.size;
                console.log(totalBytes); // like this it logs the total updated for each items in the files array
            });    
        });
    });
    //-- log out the totalBytes --
}
calcTotalSize();

PS:如果可能的话,我想只使用异步函数,而不是使用if(I == files.length)条件。

要在使用async fs.stat()完成后打印出总数,你需要一些可以控制异步流程的东西,比如async模块(不要忘记安装它:'npm install async')。下面是使用async.each():

修改后的代码
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();

您遇到此问题是因为readdirstat都是异步函数。解决这个问题最简单的方法是使用readdirSyncstatSync

您可以跟踪已读取的文件总数,例如:

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();

您可以使用以下三种选择之一(我已经按照我的偏好顺序排列):

  1. 使用promises获得回调,当所有的统计计算。

  2. 使用fs.statSync

  3. 记录你读了多少个文件,并在达到文件总数时输出总和

由于23是直接的,我将向您展示如何使用q 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);
        });
    });

在这里使用promisesfs.statSync的好处是你不会失去async io的性能,这将根据你正在读取多少文件而有所不同…