0

Before I start pulling my hair out, I thought I should ask for help first:

I'm trying to read data from a file (line by line) and count how often the first two characters in each line occur. The results are supposed to be written to a text file.

If a line starts with **, a counter is increased (recordCount) and printed to console. It does print increasing numbers to the console. If I access this or another variable below the lineReader.on() block however, they all have their initial values. How is this possible?

"use strict";

// ...

function processFile(filePath, outFile) {
    let inFile = fs.createReadStream(filePath).pipe(new bomstrip());

    let lineReader = readline.createInterface({
        input: inFile
    });
    let tagCounts = {};
    let recordCount = 0;

    lineReader.on("line", function(line) {
        let tag = line.slice(0, 2);
        tag.trim();
        if (!tag) {
            return;
        }
        else if (tag == "**") {
            recordCount++;
            console.log(recordCount); // prints increasing numbers to console
        } else {
            let val = tagCounts[tag];
            if (val === undefined) {
                tagCounts[tag] = 1;
            } else {
                tagCounts[tag]++;
            }
        }
    });

    console.log(recordCount); // prints 0, but why?!

   // ...
}

I'm using Node v5.7.0 on Windows 8.1 64bit. I also tried var instead of let, but same result.

CodeManX
  • 11,159
  • 5
  • 49
  • 70
  • 1
    That's because `lineReader.on()` is an ansynchronous event handler that fires **when** a line is read – adeneo Mar 02 '16 at 19:51
  • Good point... does it mean I can't use readline, because there's no way to read lines synchronously? Or how else can I pass the result to the outside? – CodeManX Mar 02 '16 at 19:55
  • You can't pass the result to the outside at all, you have to work with the asynchronicity, see this -> http://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call – adeneo Mar 02 '16 at 20:07

1 Answers1

1

You can still use your code, but you need to make some adjustments. If you want to print the total counts, you will have to wait until the entire file reading is finished. You can do this by listening for the 'close' event.

This piece of code might be what you're after:

"use strict";

// ...

function processFile(filePath, outFile) {
    let inFile = fs.createReadStream(filePath).pipe(new bomstrip());

    let lineReader = readline.createInterface({
        input: inFile
    });
    let tagCounts = {};
    let recordCount = 0;

    lineReader.on("line", function(line) {
        let tag = line.slice(0, 2);
        tag.trim();
        if (!tag) {
            return;
        } else if (tag == "**") {
            recordCount++;
            console.log(recordCount); // prints increasing numbers to console
        } else {
            let val = tagCounts[tag];
            if (val === undefined) {
                tagCounts[tag] = 1;
            } else {
                tagCounts[tag]++;
            }
        }
    });

    lineReader.on("close", function() {
        console.log(recordCount); // prints 0, but why?!
    });

    // ...
}
Roco CTZ
  • 1,107
  • 1
  • 16
  • 31
  • Eureka! Everything inside the close-event function runs after reading the content and has thus access to the post state. That simple change fixed it, thank you very much! – CodeManX Mar 02 '16 at 20:17
  • Awesome, glad to hear that :) – Roco CTZ Mar 02 '16 at 20:19