vmpfc1
vmpfc1

Reputation: 63

Asynchronously reading files in js

I have a list of files. I'm interested in reading out their names and the number of lines they contain. I know that there are easier ways to do this, but is there a way to accomplish this using the general structure of the code below?

var fs = require('fs');

var fileList = ['./newtest.js', './globtime.js', './newtest.js'];

var numLines = 0;
var filesCount = 0;

function returnLines () {
    console.log('the length of all files is ' + numLines);
}

function readLines(files) {
    for (file in files) {
        fs.readFile(files[file], function(err, data) {
            if (data != undefined) {
                var array = data.toString().split("\n");
                numLines += array.length;
                filesCount +=1;
                console.log('the length of ' + files[file] + ' is ' + array.length); // get this to work .. 
                if (filesCount == files.length) {
                    returnLines();
                }
            }
       });
    }
}

readLines(fileList);

Upvotes: 0

Views: 73

Answers (2)

stdob--
stdob--

Reputation: 29172

Let me rewrite your original example with promises:

var Promise = require('bluebird');    
var fileList = ['./newtest.js', './globtime.js', './newtest.js'];

readLines( fileList ).then( function(returnLines) {
  var numLines = 0;

  returnLines.forEach( function(res) {
    console.log( 'the length of ' + res.name + ' is ' + res.numLines );
    numLines += res.numLines;
  });

  console.log( 'the length of all files is ' + numLines );    
});

function readLines( files ) {    
  var promises = [];
  var result = [];
  var readFile = Promise.promisify( require('fs').readFile );

  for(i in files) {
    promises.push( readFile( files[i] )
            .bind({ index: i })
            .then( function(data) {
               result[this.index] = { 
                 name: files[this.index], 
                 numLines: data.toString().split('\n').length 
               };
            })
    )
  }

  return Promise.all( promises ).then( function() {
    return result;
  });    
} 

Upvotes: 2

mbrakken
mbrakken

Reputation: 96

You could do it with a closure:

var fs = require('fs');

var fileList = ['./newtest.js', './globtime.js', './newtest.js'];

var numLines = 0;
var filesCount = 0;

function returnLines () {
  console.log('the length of all files is ' + numLines);
}

function readLines(files) {

  var readFile = function(name){
    return fs.readFile(name, function(err, data) {
      if (data != undefined) {
        var array = data.toString().split("\n");
        numLines += array.length;
        filesCount +=1;
        console.log('the length of ' + name + ' is ' + array.length); // get this to work .. 
        if (filesCount == files.length) {
            returnLines();
        }
      }
    });
  };

  for (file in files) {
    readFile(files[file]);    
  }
}

readLines(fileList);

Upvotes: 2

Related Questions