Mix content files in nodejs

0

My code is:

var files = fs.readdirSync('./archivos/'); //itera todos los archivos 

            for (var a in files) {

                if (fs.statSync('./archivos/'+files[a]).isFile()){
                var nombreFile=files[a];
                console.log(files[a]);
                fs.readFile('./archivos/'+nombreFile, 'utf8', function(err, data) {
                console.log(nombreFile); //solo muentra el ultimo File, como solucionar?, porque solo muestra el ultimo file???
                var contentA=data;
                escritorLector.escribirTraining(nombreFile,contentA);

                for (var b in files) {
                      if(fs.statSync('./archivos/'+files[b]).isFile()){
                        if(nombreFile!=files[b]){
                            fs.readFile('./archivos/'+files[b], 'utf8', function(err, data) {
                                    var contentB=data;
                                    fs.readFile('./archivos/training/'+nombreFile, 'utf8', function(err, data) {    
                                    var contentAnterior=data;
                                    var contentAB=contentAnterior+contentB;
                                    console.log(contentAB);
                                        escritorLector.escribirTraining(nombreFile,contentAB);

                                });
                            });
                        }
                     }
                };
                });
            }
    };

that code works in 2 folders which are:

./archivos/
./archivos/training/

The logic of the code above is:

  • get the contents of all the files
  • create a new file in ./files/training/ for each file and put all the contents of all the files
  • do that for all files, that is, create for each file de ./archivos/ your union file in ./archivos/training /

in the code, comment on the following

  

console.log (filename); // just move the last file, how to solve ?, because it only shows the last file ???

    
asked by hubman 07.10.2016 в 22:02
source

1 answer

2

Apparently you're still having trouble understanding JavaScript and asynchrony. As I have explained in previous questions, JavaScript is an asynchronous language, it does not work the same as in procedural languages.

When you declare like this:

for(var a in files) {
  var file = files[a];
  fs.readFile(path, function(err, data) => {
    console.log(file);
  });
  ...
}
  

A closure is a special type of object that combines two things: a function, and the environment in which that function was created. The environment is made up of local variables that were within reach at the time the closure was created. - Mozilla docs.

This var a does not belong to for , belongs to the function . Record this well if the same thing will not always happen to you. The a reference will be remembered in the closure (callback), but not its current value . This is a very reproduced error when they start working with JS.

NOTE: You can read more about closures here .

Solution

The solution is as simple as creating a scope for the control variable that sticks to the cycle for , and this is achieved with let .

for(let a in files) {
  ...
}
  

Tip: Instead of getting the current value by files[a] use the structure for of : for(let file of files) , this way file has the current value of the array.

Extra

Your code can be seen better if you start modular . Remember, a clean code is easy to scale and maintain.

function processFilesIn(dir) {
  lookup(dir, files => {
    for(let file of files) {
      let fullName = '${dir}/${file}';
      if(isFile(fullName)) {
        read(fullName, content => {
          console.log(file);
        });
      }
    }
  });
}

function lookup(dirName, cb) {
  fs.readdir(dirName, (err, files) => {
    if(err) {
      throw err;
    }
    cb(files);
  })
}

function read(name, cb) {
  fs.readFile(name, 'utf8', (err, content) => {
    if(err) {
      throw err;
    }
    cb(content);
  });
}

function isFile(path) {
  return fs.statSync(path).isFile();
}

How to use:

try {
  processFilesIn('directorio');
} catch(e) {
  // maneja el error: e.name, e.message
}

You can even make your code more readable by extending Error and creating Custom Errors.

    
answered by 07.10.2016 / 22:56
source