nickewing / line-reader

Asynchronous line-by-line file reader for node.js
MIT License
453 stars 75 forks source link

Await finished function #40

Closed dlarr closed 6 years ago

dlarr commented 6 years ago

Hello,

I have this case where I need to read lines from several flat files, and I loop over them. I would like to be able to wait the processing of all files before I go on.

Of course, sync reading is needed but I can't get it to work. In the method below, controlFiles mean reading the 1st line of all files. I want this step to be completed before I move anything.

try {
    // Controlling all files => Reading the 1st line of each 
    await controlFiles.controlMediapostFiles();

    // Moving files to files_out directory
    await moveFiles.moveFilesToDir(filePath, files_out, files_done, false);
} catch (error) {
    // what ever
}

No here is how I TRY to get this done sync :

controlMediapostFiles: async function () {
    return new Promise(async (resolve, reject) => {
    try {

        let numberOfFiles = 0;

            // FOR EACH FILES IN DIRECTORY
        await fs.readdirSync(files_out).forEach(async function (file) {

            numberOfFiles++;

            let lineNumber = 0;

                // TRY AND WAIT FOR FINISHED EVENT (EOF or return false)
            await lineReader.eachLine(files_out + path.sep + file, await function(line) {
                lineNumber++;
                if (lineNumber === 1) {
                    // somthing
                    console.log(line)
                } else {
                    return false;
                }
            });
            }
    });

    if (numberOfFiles === 0){
        reject({done:false, step: 'CONTROLE', message: 'Aucun fichier fourni'});
    }

    resolve({done:true, message: 'Control OK'});

   } catch (error) {
    reject(error);
   }
});
}

No matter how I try, the operations (including moving files and logging) in the method AFTER are done before the reading of the file.

Note that I can't use the method here after, since it's a for each files loop:


lineReader.eachLine(bufferStream, function(line) {
    //do stuff
}, async function finished (err) {
     // called when reading is finished
});
dlarr commented 6 years ago

Hello, , I found a way to achieve what I needed: Not using this lib anymore sorry :(


class Splitter extends Transform {
    constructor(options){
        super(options);
        this.splitSize = options.splitSize;
        this.buffer = Buffer.alloc(0);
        this.continueThis = true;
    }
    stopIt() {
        this.continueThis = false;
    }

    _transform(chunk, encoding, cb){

        this.buffer = Buffer.concat([this.buffer, chunk]);

        while ((this.buffer.length > this.splitSize || this.buffer.length === 1) && this.continueThis){
            try {
                let chunk = this.buffer.slice(0, this.splitSize);

                this.push(chunk);
                this.buffer = this.buffer.slice(this.splitSize);
                if (this.buffer[0] === 26){
                    console.log('EOF : ' + this.buffer[0]);
                }
            } catch (err) {
                console.log('ERR OCCURED => ', err);
                break;
            }
        }
        console.log('WHILE FINISHED');
        cb();
    }
}

The to read your stuff simply do

let bufferStream = new stream.PassThrough();
bufferStream.end(hugeBuffer);
let splitter = new Splitter({splitSize : 170}); // In my case I have 170 length lines, so I want to process them line by line
let lineNr = 0;
bufferStream
      .pipe(splitter)
      .on('data', async function(line){

          line = line.toString().trim();

          splitter.pause(); // pause stream so you can perform long time processing with await
          lineNr++;

         if (lineNr === 1){
              // DO stuff with 1st line

         } else {
              splitter.stopIt(); // Break the stream and stop reading so we just read 1st line
         }

         splitter.resume() // resumestream so you can process next chunk
    }).on('error', function(err){
            console.log('Error while reading file.' + err);
            // whatever
     }).on('end', async function(){
           console.log('end event');

           // Stream has ended, do whatever...

    });